Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
139
rated 0 times [  143] [ 4]  / answers: 1 / hits: 17079  / 7 Years ago, mon, february 27, 2017, 12:00:00

When updating a stateful component in React is it considered a bad practice when a component uses the current state to update the new state.



For example if I have a class that stores whether a filter is open or not in it's state, is one of these options for updating the state more desirable than the other in terms of performance?



Option 1:



class Container extends Component {
state = {
show: false
}

show = () => this.setState({ show: true })

hide = () => this.setState({ show: false })

render() {
<ExternalComponent
show={this.show}
hide={this.hide}
/>
}
}


Option 2:



class Container extends Component {
state = {
show: false
}

toggleVisibility = () => this.setState({ show: !this.state.show })

render() {
<ExternalComponent
toggleVisibility={this.toggleVisibility}
/>
}
}


Option 3:



class Container extends Component {
state = {
show: false
}

setShow = (newVal) => this.setState({ show: newVal })

render() {
<ExternalComponent
setShow={this.setShow}
/>
}
}

More From » reactjs

 Answers
26

There is nothing wrong with a component accessing its own state. Write-only state wouldn't be terribly useful! However, you should be very careful when exposing component state or state-altering methods to other components. Component state is internal, and should only been touched from outside via a well-considered interface, to prevent your components from becoming an entangled mess.



In fact, there is an example that is similar to your Example #2 in the React documentation:



class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};

// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}

render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}

ReactDOM.render(
<Toggle />,
document.getElementById('root')
);


Note a difference from your example, however. The toggle method needs to be bound in the constructor, to ensure that this means what you're expecting it to mean.



If the wrapping component is the one keeping track of the visibility of the child ExternalComponent, then rather than passing the toggle method into the child component, I would expect the wrapper to render a hide/show affordance of some sort, and then either pass the current visibility into the child component as a prop or selectively render it (note that selective rendering will cause the entire child component to be remounted when it's enabled again, which may be expensive; you may be better off hiding it than tearing it down and recreating it). That makes the division of concerns clear: the wrapper knows about visibility, and the child component doesn't need to know how or why that decision was made, nor does it need to touch the wrapper's internal state.


[#58751] Saturday, February 25, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
grayson

Total Points: 36
Total Questions: 113
Total Answers: 95

Location: Tonga
Member since Fri, Aug 21, 2020
4 Years ago
grayson questions
;