skip to Main Content

I am trying to exchange several data variables between multiple elements in React, essentially the equivalent of passing a pointer to a struct in C++ between various classes/functions

I am following this tutorial
https://react.dev/learn/sharing-state-between-components

I am using flask on backend to serve the /data route. This part works without issues.

However the error I get in console is act-dom.production.min.js:189 TypeError: "activeState" is read-only

How can I modify this code so that I can set activeState variable from within ToolbarElement?

Thanks

Here is my code:

function App() {

  activeState = {
    graph_data: 0,
    other_data: 1,
  }

  const [activeState, setActiveState] = useState();

  return (
    <div className="App">
      <div className="App-body">
        <div className="toolbar-element" style={{ top: "50px", left: "0px" }}>
          <ToolbarElement
            active_state={activeState}
            updateState={(state) => setActiveState(state)}
          />
        </div>
        <div className="graph-element" style={{ top: "50px", right: "0px" }}>
          <GraphElement
            active_state={activeState}
            updateState={(state) => setActiveState(state)}
          />
        </div>
      </div>
    </div >
  );
}

export default App;

ToolbarElement.js

function ToolbarElement({
  active_state,
  updateState
}) {


  const [data, setdata] = useState({
    lst: [],
  });

  const handleButtonClick = () => {
    console.log('Button clicked!');
    fetch("/data").then((res) =>
      res.json().then((data) => {
        // Setting a data from api
        setdata({
          lst: data,
        });
      })
    );
    active_state.graph_data = data.lst[0];
    updateState(active_state);
  };
  
  return (
    <div style={{ height: '33.33%', backgroundColor: '#F0F0F0' }}>
      <button onClick={handleButtonClick}>Click me!</button>
    </div>
  );
}

export default ToolbarElement;

GraphElement.js

function GraphElement({
  active_state,
  updateState
}) {    

  return (
    <div style={{ height: '33.33%', backgroundColor: '#E8E8E8' }}>
      <p>{active_state.graph_data}</p>
    </div>
  );
}

export default GraphElement;

2

Answers


  1. The issue is with your ‘handleButtonClick’ callback. You’ve taken the existing state object and modified its graph_data property with:

       active_state.graph_data = data.lst[0];
    

    Instead you should simply call updateState with a new object for your state.

    e.g.

       updateState({ ...active_state, graph_data: data.lst[0] });
    
    Login or Signup to reply.
  2. This line here..

     active_state.graph_data = data.lst[0];
    

    You are trying to mutate active_state. You can not update state in react by mutating state. This line needs to be removed.

    Instead you need to call the state setter you have defined.

    setActiveState((prevState)=> ({...prevState, graph_data:data.lst[0]}))
    

    I am using the functional method of updating state because you have an object as state. So we are maintain the other values of the object by spreading prevState

    something I just notices as well, you need to set your initial state like so..

        const [activeState, setActiveState] = useState({
          graph_data: 0,
          other_data: 1,
        });
    

    and you should also remove the activeState object from App


    Edit to refactor your code:

    Update app to:

    function App() {
      
      const [activeState, setActiveState] = useState({graph_data:0, 
      other_data:1});
    
      return (
        <div className="App">
          <div className="App-body">
            <div className="toolbar-element" style={{ top: "50px", left: "0px" }}>
              <ToolbarElement
                setActiveState={setActiveState}
              />
            </div>
            <div className="graph-element" style={{ top: "50px", right: "0px" }}>
              <GraphElement
                active_state={activeState}
              />
            </div>
          </div>
        </div >
      );
    }
    
    export default App;
    

    update toolbar element to:

    function ToolbarElement({
      setActiveState
    }) {
    
    
      const handleButtonClick = () => {
        console.log('Button clicked!');
        fetch("/data").then((res) =>
          res.json().then((data) => {
            // Setting a data from api
            setActiveState((prevState)=> ({...prevState, 
             graphq_data:data[0]}))
          })
        );
    
      };
      
      return (
        <div style={{ height: '33.33%', backgroundColor: '#F0F0F0' }}>
          <button onClick={handleButtonClick}>Click me!</button>
        </div>
      );
    }
    
    export default ToolbarElement;
    

    upadate graph element to :

    function GraphElement({
      active_state,
    }) {    
    
      return (
        <div style={{ height: '33.33%', backgroundColor: '#E8E8E8' }}>
          <p>{active_state.graph_data}</p>
        </div>
      );
    }
    
    export default GraphElement;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search