Calling Stitches createStitches for every component in React - reactjs

I'm using Stitches to write my CSS in a React application, mainly for the theming and variables. I'm calling createStitches in every component file, like so:
ComponentA.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentA;
ComponentB.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentB;
And then I'm importing these components and using them in App.tsx:
import ComponentA from "./components/ComponentA";
import ComponentB from "./components/ComponentB";
function App() {
return (
<div className='App'>
<ComponentA />
<ComponentB />
</div>
)
}
I know I can just call the createStitches in the App.tsx file once, but I like keeping my components self-sufficient, as in they should work without any other extra work. Is this a bad approach, or is this something that is fine to do? Does React call the function many times, or just once? Thanks for any help!

You do not need to call createStitches for every component. This function is to create configuration for your application styling. I don't that you are going to have separate configuration for every component.
This will just cause extra work. Just keep the createStitches in a common file and import it from there

Related

What happens if two components import the same CSS file in React?

Let's say I have two React components:
import { React } from "react";
import "./styles.css";
function ComponentA() {
...
}
export default ComponentA;
import { React } from "react";
import "./styles.css";
function ComponentB() {
...
}
export default ComponentB;
Both of these components are importing the same CSS file styles.css. Now let's say that in my app, I'm importing both of these components, so App.js looks something like this:
import { ComponentA } from "./ComponentA";
import { ComponentB } from "./ComponentB";
function App() {
return (
<div className="App">
<ComponentA />
<ComponentB />
</div>
);
}
export default App;
What exactly happens here? Does my app import the same CSS file twice? And if so, do I just make the import on the App.js file instead?
It's as if it was only imported once.
When a module bundler like Webpack sees an import, it puts the following path in the list of files to process, if the path doesn't exist already. The file is only processed once, no matter how many times it's imported.
Note that with React apps, you will often see
import React from "react";
in tens or hundreds of files - React isn't created anew hundreds of times. Rather, the module is processed once, and then files that import it are given access to what React has exported.
Importing CSS files works the same way, in that they're only processed once no matter how many times an import exists for them (though they don't really have exports, just side-effects).
If both ComponentA and ComponentB depend on styles.css, feel free to keep importing styles.css in both - it doesn't hurt, and will make things easier to manage when you can see at a glance that both components directly depend on that CSS.

React context API when wrapped around index.js file it's display nothing

I am learning about context API and creating an add basket functionality in the Context.js file I have created a context that which will I use for my application it's code is
import React, { createContext } from "react";
const Cart = createContext();
function Context({ childern }) {
return <Cart.Provider>{childern}</Cart.Provider>;
}
export default Context;
now I am wrapping my App component around it in the index.js file
import Context from "./context/Context";
<Context>
<App />
</Context>
but after doing this on the browser it display nothing no error not a single component that I have created is displayed but when I unwrapped the component it works fine
function Context({ props }) {
return <Cart.Provider>{props.childern}</Cart.Provider>;
}
Now it will work. Just add "props" in props and "props.children" in provider.

Moving variables from one file to the other in React JS

I'm a noob with React JS and I'm trying to understand how to export a variable from a file and import it into another. What I tried is this:
File App.js:
import React from 'react'
function App() {
[hi, setUpHi] = useState('Hello World')
return (
<div className='App'>
<Test />
</div>
);
}
export default App
export {hi}
File Test.js:
import React from 'react'
import {hi} from './App'
function Test() {
return (
<div>
{hi}
</div>
)
}
export default Test
But this doesn't work :(
It says that hi is not defined. I tried to define it outside of the function, this also doesn't work. Can anybody help me?
ps:
I know that I could do it easier by using props:
<Test hi = {'Hello World'} />
and then
function Test({hi}) ... \\ etc.
But with this example, I want to understand how to export and import variables, which might be much easier than passing props. (Or am I wrong with this assumption?)
Looks like you are trying to reference the "hi" variable outside of it's function scope (it's declared in the component, not at root level) - hence why it's undefined in the global scope.
Also, FYI it's an antipattern to use component state in this way. State is internal to the FunctionComponent App and exposing it's state in this way could compromise component purity.
If your intention is to share state between components, either pass them through props, or use a custom hook.

What does this part of the Redux document mean?

I'm using the Redux-tool kit to set it up. We are now using #testing-library/react to set up testing-related settings.
I got a question while looking at the official document.
// test-utils.js
import React from 'react'
import { render as rtlRender } from '#testing-library/react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
// Import your own reducer
import reducer from '../reducer'
function render(
ui,
{
initialState,
store = createStore(reducer, initialState),
...renderOptions
} = {}
) {
function Wrapper({ children }) {
return <Provider store={store}>{children}</Provider>
}
return rtlRender(ui, { wrapper: Wrapper, ...renderOptions })
}
// re-export everything
export * from '#testing-library/react'
// override render method
export { render }
What function does this part have in the code part above?
// re-export everything
export * from '#testing-library/react'
// override render method
export { render }
I don't know this library, but export * from '#testing-library/react' just means that anything you can import from #testing-library/react, you can now import directly from this file, test-utils.js.
I guess that they found it convenient to have a way to access just the react testing modules in one place, with the render method overwritten with their own custom version defined above.
They are basically creating their own aliased copy of the React Testing Library package where everything is the same except for the render function. This setup is explained in more detail in the testing library docs section Setup: Custom Render.
The custom render function takes the same arguments as the original render function from #testing-library/react so that they can be used interchangeably (though it adds support for extra properties initialState and store in the options object). Internally, the custom render function calls on the library's render function, which they import with an aliased name rtlRender, but it sets a default property for the wrapper option so that components will be rendered inside of a redux Provider component.
Now to the confusing exports. export * from '#testing-library/react' takes all of the exports from the testing library and re-exports them. export { render } overrides the previously exported render function with the custom one, so it needs to come after the export *.
As for why they would create the function in one place and then export it later rather than just doing export function, I think that's just a matter of code style preference. This seems to work fine, as far as I can tell:
import { render as rtlRender } from "#testing-library/react";
// re-export everything
export * from "#testing-library/react";
// override render method
export function render(somethingCustom, ui, { ...renderOptions } = {}) {
return rtlRender(ui, { ...renderOptions });
}

NEXT JS - How to prevent layout get re-mounted?

Trying next with layout pattern:
https://github.com/zeit/next.js/tree/canary/examples/layout-component
And the problem is that Layout component get remounted on every page change. I need to use layout component as a Container so it'll fetch data from server on every mount. How can I prevent layout to get re-mounted? Or am I missing something there?
This helped me for persistent layouts. The author puts together a function that wraps your page components in your Layout component and then passes that fetch function to your _app.js. This way the _app.js is actually the components that renders the Layout but you get to specify which pages use which layout (in case you have multiple layouts).
So you have the flexibility of having multiple layouts throughout your site but those pages that share the same layout will actually share the same layout component and it will not have to be remounted on navigation.
Here is the link to the full article
Persistent Layout Patterns in Next.js
Here are the important code snippets. A page and then _app.js
// /pages/account-settings/basic-information.js
import SiteLayout from '../../components/SiteLayout'
import AccountSettingsLayout from '../../components/AccountSettingsLayout'
const AccountSettingsBasicInformation = () => (
<div>{/* ... */}</div>
)
AccountSettingsBasicInformation.getLayout = page => (
<SiteLayout>
<AccountSettingsLayout>{page}</AccountSettingsLayout>
</SiteLayout>
)
export default AccountSettingsBasicInformation
// /pages/_app.js
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps, router } = this.props
const getLayout = Component.getLayout || (page => page)
return getLayout(<Component {...pageProps}></Component>)
}
}
export default MyApp
If you put your Layout component inside page component it will be re-remounted on page navigation (page switch).
You can wrap your page component with your Layout component inside _app.js, it should prevent it from re-mounting.
Something like this:
// _app.js
import Layout from '../components/Layout';
class MyApp extends App {
static async getInitialProps(appContext) {
const appProps = await App.getInitialProps(appContext);
return {
...appProps,
};
}
render() {
const { Component, pageProps } = this.props;
return (
<Layout>
<Component {...pageProps} />
<Layout />
);
}
}
export default MyApp;
Also, make sure you replace all the to <Link href=""></Link>, notice that only have change the Html tag to link.
I struggled because with this for many days, although I was doing everything else correctly, these <a> tags were the culprit that was causing the _app.js remount on page change
Even though this is the topic Layout being mounted again and again, the root cause of this problem is that you have some data loaded in some child component which is getting fetched again and again.
After some fooling around, I found none of these problem is actually what Next.Js or SWR solves. The question, back to square one, is how to streamline a single copy of data to some child component.
Context
Use context as a example.
Config.js
import { createContext } from 'react'
export default createContext({})
_App.js
import Config from '../Config'
export default function App({ Component, pageProps }) {
return (
<Config.Provider value={{ user: { name: 'John' }}}>
<Component {...pageProps} />
</Config.Provider>
)
}
Avatar.js
import { useContext } from 'react'
import Config from '../Config'
function Avatar() {
const { user } = useContext(Config)
return (
<span>
{user.name}
</span>
)
}
export default Avatar
No matter how you mount and dismount, you won't end up with re-render, as long as the _app doesn't.
Writable
The above example is only dealing with readable. If it's writable, you can try to pass a state into context. setUser will take care the set in consumer.
<Provider value={useState({})} />
const [user, setUser] = useContext(Config)
setUser is "cached" and won't be updated. So we can use this function to reset the user anytime in child consumer.
There're other ways, ex. React Recoil. But more or less you are dealing with a state management system to send a copy (either value or function) to somewhere else without touching other nodes. I'll leave this as an answer, since even we solved Layout issue, this problem won't disappear. And if we solve this problem, we don't need to deal with Layout at all.

Resources