skip to Main Content

I need to pass value of state step from component Step to component App as I am going to pass that as a props to another child component (not presented in the code).
Initially, I tried to use lifting up, but could not synchronise step and count – count is less by 1.

The code is here: https://codesandbox.io/s/sparkling-violet-cn7glt

Then, I used useEffect hook,

code is here: https://codesandbox.io/s/kind-colden-pcthvq

and included step variable in dependency array, it worked but I suppose that the task might be solved by using only lifting states up without useEffect, would be grateful for your advices.

2

Answers


  1. It might be a bit overwhelming to control your states in that way. Let’s consider to use Context component.

    React Docs – Context

    It allows to avoid heavy prop drilling and gives clearer and better way to control your states (in case when you do not want to use some third party State Management Systems).

    Pseudocode

    1. Create Context Component
    2. Create Provider and pass your states via "value" attribute
    3. Inside child component import your Context and pass it into "useContext" hook
    4. Feel free to set/ use your states inside of any child inside Provider

    Quick Example:

    MyContext.js

    import React from "react";
    export default MyContext = React.createContext();
    

    App.js

    import { useState } from "react";
    import MyChildComponent from "./components/MyChildComponent"
    import MyContext from "./components/MyContext";
    
    function App(){
        const [count, setCount] = useState(0)
    
        return(
            <MyContext.Provider value={[count, setCount]}>
                <MyChildComponent />
                // notice that we do not drill any props. That is our context job to do
            </MyContext.Provider>
        )
    

    MyChildComponent.js

    import { useContext } from "react";
    import MyContext from "./MyContext";
    // notice that we need to import useContext hook and "MyContext" component
    
    function MyChildComponent(){
        const [count, setCount] = useContext(MyContext)
        // from now on we have an access to the state we declared inside App.js file
        // any changes you will do in here will affect all components which are using "count" state
       
        const handler = () => {
           setCount((prev)=>prev+1)
        }
        render(
            <button onClick={handler}>{count}</button>
        )
    }
    
    

    Also I made some small refactory of you code so go and have a look (starting from MyContext.js file). In there I wrote some comments below so you can follow the steps.

    REFACTORY – SANDBOX

    Login or Signup to reply.
  2. If you find yourself trying to synchronize two states with eachother, it’s often sign that they shouldn’t be two states in the first place. Instead, just have one state. The child components should use the props they’re given directly and not copy them into states which then need to managed independently.

    // App.js
    function App() {
      const [count, setCount] = useState(1);
      const addCount = () => {
        setCount(prev => prev + 1);
      };
      return (
        <>
          <span>App {count}</span>
          <Step value={count} addCount={addCount} />
        </>
      );
    }
    
    // Step.js
    function Step({ value, addCount }) {
      return (
        <>
          <Plus value={value} addCount={addCount}>
          <span>Step{value}</span>
        </>
      );
    }
    
    // Plus.js
    function Plus({ value, addCount }) {
      return <button onClick={addCount}>+</button>;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search