2

So after coding a complete web application with react with props-drilling so deep like you've never seen before, you shouldn't, I've decided to give react 'contexts' a go. I read the react documentation, and I've decided to make my states(which seriously need help because they're so deeply rooted into components after components) in a separate file:

-create a 'context.js' filee

-Inside I'm gonna have: [and notice I have two states inside]

import { createContext } from 'react'
export const context = createContext();
export default function ContextProvider (props) {
    const [state1, setState1] = useState();
    const [state2, setState2] = useState();
    return (
        <context.provider value={[state1, setState1, state2, setState2]}>
            props.children
        </context.provider>
       )
}
  • Now all I have to do is import this component where I want to make these states visible, use destructuring like so:
//inside a functional component
...
const [state1, setState1] = useContext(context); //assuming I only need state1 in this component
...

Now my question is how efficient this approach is. And in some blogs I read about using context with hooks, every one I read used 'useReduce' hook. Could someone explain why 'useReduce' was used, that is what problem does it solve and how. That'll be appreciated.

2 Answers2

0

This is not efficient at all: any time you call setState1() it will cause re-render of <ContextProvider>, and thus of entire app, which is presumably wrapped into <ContextProvider>.

Consider to check my library for global state management with context: https://www.npmjs.com/package/@dr.pogodin/react-global-state :)

Sergey Pogodin
  • 321
  • 1
  • 6
  • oh yes, how did I miss that. So how would you recommend to do things that I want to do? I.e, manage mutltiple states with contexts. Or is there no other option than to create a separate contexts for each state. –  Apr 26 '21 at 17:23
  • Use my lib :D Or, dig into its code to see how it works. It also has a context provider, which holds "GlobalState" object. Any amount of data you need, are stored at different paths of that object, and it uses a tricky system allowing separate components to update and watch different global state paths. But as the end user you just do in components `const [value, setValue] = useGlobalState('some.path', 'initial_value')` < just as with the local state, and whenever you change value, it only triggers re-render of components watching that state path, or any parent path. – Sergey Pogodin Apr 26 '21 at 17:59
0

I feel like this this question is pretty relevant here: Fast changing states without Redux (at the end of the day, useReducer and useState should be equally efficient in terms of performance? I'm not an expert here though). Also, useReducer is better for handling complex state, which usually happens when you start using Contexts or Redux.

If you want to have an object like this in your state

user: {
  options: { ... },
  settings: { ... }
}

You REALLY should use useReducer (especially if you're in a situation where changing in the options relies on knowing what the settings are) and have the complicated logic be handled through the dispatch, rather than jumping through hoops and trying to get it to work with useState. At the end of the day, they do pretty much the same thing in that they "handle state", if you want to know more about the nuances, best way to do it is to read the docs: https://reactjs.org/docs/hooks-reference.html#usereducer.

Again, I'm not an expert but I've made a fair few attempts at looking into "performance in React" and from what I've gathered, rerenders due to state change are rarely the problem. Usually you'll have something in a child component that relies on performing an expensive calculation on a prop, and the correct solution isn't to "prevent the rerender" but instead to do something like "move the expensive calculation up" so it only needs to happen once per render rather than n children per render.

Michael Hoobler
  • 634
  • 6
  • 14