Home > OS >  How to get the child state data back to parent
How to get the child state data back to parent

Time:08-25

In my react project, I have been developing my child components all the way until now. In child, it has its own state, and its state is a state of obj with a very long and complicated key value pair. And in it, its state have been referencing here and there.

At some point, in the parent, I need to have a button to gather all child's state data, for some aggregation.

To do that, I know I can reinvent everything again, I can do prop drilling from parents and let not child have it own state, and once the child call set function, Parent can have every child state.

The problem is that Child components has been developed for long, so I dont want to change its structure.

Q: Simply put, without removing child state and re create state from parent, How can I get all child state data from parent easily?

To better illustrate it, below is a simply example code that can be enough to explain the problem

import React, { useState } from "react";

export function App(props) {
  return (
    <>
      <div className="App">
        <Child name="child1"></Child>
        <Child name="child2"></Child>
        <Child name="child3"></Child>
      </div>
      //Later at some point, I need to aggreate back all the data in child for aggreate action.
      <div>
        <button>Print out all the state data in children</button>
      </div>
    </>
  );
}

const Child = (props) => {
  const { name } = props;

  const [data, setData] = useState("");

  return (
    <div>
      <input onChange={(e) => setData(e.target.value)}></input>
      <p>
        Input in {name}: {data}
      </p>
    </div>
  );
};

CodePudding user response:

There is no way to get back data from the child states. In order to achieve this feature, you must either pass props to the child component from the parent component or use the redux. If you do not want to use both redux and pass props to the child component, we can use local storage or session storage. You just have to set the child's states in the local or session storage using the useEffect hook with the state dependency. When you click the button on the parent component, get the data from local or session storage back and use them as per your requirement. But this is a very bad idea. we should use state management libraries like redux or context api.

CodePudding user response:

Here's a demo of the Context API.
It's a simple 3x3 Tic-Tac-Toe game. The state flow is explained in the comments.

let GameContext = React.createContext()

function Square({row, column}) {
    let context = useContext(GameContext);
    // here the child sets the state of the parent using setLetter
    // that was passed to child through the context
    return <div onClick={(evt)=>{context.setLetter(row,column)}}>
               {context.board[row][column]}
           </div>;
}

class Board  {

    constructor(props) {
        super(props);
        this.state = {
            board: Array.from({length:3},()=>Array.from({length: 3})),
            turn: 'O',
            // a method to update the state, is present in the state itself
            // & is passed to children through context
            // calling this method allows the child to update state of parent
            setLetter: (row,column)=> {
                this.setState((prevState)=> ({
                    board: prevState.board.map((line,r)=>(
                               line.map((lett,c)=> (
                                   (row==r && column == c)?prevState.turn:lett
                               )
                           ),
                    turn: (prevState.turn=='O')?'X':'O'
                });
            }
        };
    }
    
    render() {
        // the parent passes the state to the child through the context
        return <GameContext.Provider>{(value)=> {
            value.board.map((line,r)=>(
                line.map((lett,c)=> (
                    <Square row={r} column={c} />
                ))
            )
        }}</GameContext.Provider>;
    }
}

 

Fore more details on the Context API, this is a good article that explains well.

  • Related