0
votes

I am new to React and was struggling with where we need to keep state in React. I came across an example which puts state in parent component and get access to that state via props. That is, there is Accordion component and the Accordion is either in the “open” state, or the “closed” state, and we store that information as a flag inside the parent component’s state (not inside the Accordion). We tell the Accordion which way to render by passing isOpen as a prop. When isOpen is true, it renders as open. When isOpen is false, it renders as closed.

*The question is Why do we need to keep state in parent component since we can keep state in Accordion component and manage it in there. *

3
You have to keep the state at the highest level it is needed. Its left for you to determine the highest component it is needed.Ken Sawyerr

3 Answers

2
votes

In your example, if only the Accordion needs the state that's probably a better place (the example may not be correct). In general, a good rule to follow is keeping state as "specific" or as "narrow" as possible.

State only needs to be raised up in the tree (to its parent or an earlier ancestor) if other components that are children of those ancestors also need access.

However, if in your example, say the AccordionParent is rendering a different UI or doing something with isOpen then that's probably a good place for it (because it's generally a bad idea to expose a child's state to its parent).

1
votes

if isOpen just used in Accordion, it is better to keep the state in Accordion.
but sometimes state isOpen is used by others like

<>
 <Accordion isOpen={this.state.isOpen} />
 {<ToggleButton onClick={()=> this.setState({isOpen: !this.state.isOpen})} />}
</>

than you have to keep isOpen in parent

0
votes

Like so many things in React, it depends on the use that you are gonna give to the isOpen variable, if you are looking only using it inside a <Accordion /> component, you could have it as a local state for it, like this:

class Accordion extends Component {
  state = { isOpen: false }

  // Use to close the <Accordion />
  closeAccordion = () = {
    this.setState({ isOpen: false });
  }

  render() {
    return(...Code for the <Accordion />)
  }
}

Another case would be if you would like to use the isOpen variable for another component or function not only the <Accordion />, like this:

class Wrapper extends Component {
  state = { isOpen: false };

  // Handle the click of the <Button />
  handleClick = () => {
    const { isOpen } = this.state;

    this.setState({ isOpen: !isOpen })
  };

  render() {
  const { isOpen } = this.state;

    return(
      <>
        <Accordion isOpen={isOpen} />
        <Button onClick={this.handleClick} />
      </>
    )
  }
}