Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset child elements' state?

Let's say I have three elements that hold in state a counter that increments when clicked.

If I click on one element, how do I reset the other counters to 0?

https://jsfiddle.net/69z2wepo/56827

const Parent = React.createClass({
    render() {
        const rows = [];
        for (let i = 0; i < 3; i++) {
            rows.push(<Child key={i} />);
        }
        return (
            <ul>
                {rows}
            </ul>
        );
    }
});

const Child = React.createClass({
    getInitialState() {
        return {counter: 0};
    },
    handleClick() {
        this.setState({counter: ++this.state.counter });
    },
    render() {
        return (
            <div onClick={this.handleClick}>
                {this.state.counter}
            </div>
        );
    }
});

ReactDOM.render(
    <Parent />,
    document.getElementById('app')
);
like image 297
Matthew Avatar asked Sep 18 '16 10:09

Matthew


People also ask

How do I reset my state value?

To reset a component to its initial state:Store the initial state in a variable. When an event occurs, call the setState() function, passing it the initial state.

Can child components change state?

The state is a variable like other variables in a JavaScript app. It is only accessible inside a component. You can pass the state to other child components, and you can also change the state from the child components.

How do you change the state of parent from child in functional component?

React hooks are introduced in React 16.8. If you are familiar with the class components then there is no difference to change the parent component state from child component. In both cases, you have to pass the callback function to the parent.


3 Answers

It you really can't lift the state into the parent component as other answers have suggested, a hacky way to do this is to just change the key prop of an element. This causes React to unmount the element with the old key and mount a new instance.

class ChildComponent extends React.Component {
  state = {
    count: 0
  };
  render() {
    const { count } = this.state;
    return (
      <div>
        <div>count: {count}</div>
        <button onClick={() => this.setState({ count: count + 1 })}>Increment</button>
      </div>
    );
  }
}

class ParentComponent extends React.Component {
  state = {
    stateBustingKey: 0
  };
  render() {
    const { stateBustingKey } = this.state;
    return (
      <div>
        <ChildComponent key={stateBustingKey} />
        <button
          onClick={() =>
            this.setState({ stateBustingKey: stateBustingKey + 1 })
          }
        >
          Reset
        </button>
      </div>
    );
  }
}

ReactDOM.render(<ParentComponent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />
like image 75
tlrobinson Avatar answered Oct 22 '22 14:10

tlrobinson


Component parent in this case should be managed the state of children.

Check this:

const Parent = React.createClass({
    getInitialState() {
        return {counter: 0, id: 0};
    },
    handleClick(id) {
        if(this.state.id == id){
            this.setState({counter: ++this.state.counter, id: id });
        } else {
            this.setState({counter: 1, id: id });   
        }

    },
    getCounter(id){
        if(id == this.state.id){
            return this.state.counter;
        } else {
            return 0;
        }
    },
    render() {
        const rows = [];
        for (let i = 0; i < 3; i++) {
            rows.push(<Child key={i} counter={this.getCounter(i)} handleClick={this.handleClick} id={i} />);
        }
        return (
            <ul>
                {rows}
            </ul>
        );
    }
});

const Child = React.createClass({

    render() {
        return (
            <div onClick={this.props.handleClick.bind(null, this.props.id)}>
                {this.props.counter}
            </div>
        );
    }
});

ReactDOM.render(
    <Parent />,
    document.getElementById('app')
);

JsFiddle

like image 44
Piotr Białek Avatar answered Oct 22 '22 14:10

Piotr Białek


That would be a little hard since your Child components are managing their own state.

You can convert them into dumb components and manage their state in your Parent component.

Something like this

const Parent = React.createClass({
    getInitialState() {
        return {counters: [0,0,0]};
    },
    handleClick(index){
       let newCounterState = this.state.counters.map(() => 0);
       newCounterState[index] = this.state.counters[index] + 1 ;
       this.setState({counters : newCounterState})
    },
    render() {
        const rows = this.state.counters.map((value,index) => (
            <Child 
               key={index}
               handleClick={() => this.handleClick(index)}
               counter={value}
            />
        ))
        return (
            <ul>
                {rows}
            </ul>
        );
    }
});

const Child = ({counter,handleClick}) => (
    <div onClick={handleClick}>
      {counter}
  </div>
)

ReactDOM.render(
    <Parent />,
    document.getElementById('app')
);

jsfiddle

like image 43
QoP Avatar answered Oct 22 '22 12:10

QoP