20
votes

I have a list of components and want to set each component as selected when the user clicks on it.

The flow looks like

Dashboard
 ⎿ MyList
    ⎿ MyItem -> onClick -> setState({active:true})

I've got the selected part done by using state but I'm left wondering how to deactivate all the other elements.

2

2 Answers

21
votes

By definition, state is not accessible from outside the component. And always copying props to state is not recommended.

In your component tree structure. you should set the selected item as state in the parent (not in the item).

And pass the selected Id to each item as a prop.

In the child render, you can do something like

let itemIsSelected = (this.props.itemId == this.props.selectedId);

And pass a method from parent to child, and then include that as:

onClick={() => this.props.setSelected(this.props.itemId)}

In the official docs, there is a good explanation on how to structure components. This may be helpful to determine whether something should be state or props, or whether stuff is better managed inside child or parent.

6
votes

Dan Abramov mentions another clever way to access a state change from outside a component class. Technically the setState function still has to be called from within the component class anyway, so it's not REALLY outside the component, but this allows you to set the state of different components in the same fashion if you want, from the returned value of a function.

Basically, you can pass in a function into the setState() function, and the state will be set to the returned value of that function.

you can see his post here: https://twitter.com/dan_abramov/status/824308413559668744?lang=en