ReactJs: state change in response to state change

I have a React component with input and an additional "advanced input":

[ basic ] Hide Advanced... [ advanced ] 

The advanced bottom will go away if you click "Hide advanced", which changes to "Show advanced". It simply and works fine, there is a showAdvanced key in a state that controls the text and whether advanced input is displayed.

External JS code, however, can change the value of the extended one, in which case I want to show the [advanced] input if it is currently hidden, and the value is different from the default value. The user should be able to click "Hide advanced" to close it again.

So, someone has external calls to cmp.setState({advanced: "20"}) , and I want to show advanced; The easiest task is to simply update showAdvanced in my state. However, there seems to be no way to update some state in response to other state changes in React. I can come up with a few workarounds with slightly different behavior, but I really want to have this specific behavior.

Should I move showAdvanced to the details, would that make sense? Can you change props in response to state changes? Thanks.

+5
source share
2 answers

Ok, first point out that a third party outside your component might call cmp.setState() ? This is a huge no-no reaction. A component should only ever call its own setState function — nothing outside should call it.

It should also be remembered that if you try to change state again in response to a state change, it means that you are doing something wrong.

When you build things this way, it makes your problem a lot harder than necessary. The reason is that if you agree that nothing external can establish the state of your component, then basically the only option you have is to allow external things to update the details of your component and then respond to them inside your component. This simplifies the problem.

So, for example, you should look at what external things that used to call cmp.setState() , instead call React.renderComponent on your component again, giving a new prop or prop value like showAdvanced set to true , then your a component can respond to this in componentWillReceiveProps and set it accordingly. Here is an example of a bit of code:

 var MyComponent = React.createClass({ getInitialState: function() { return { showAdvanced: this.props.showAdvanced || false } }, componentWillReceiveProps: function(nextProps) { if (typeof nextProps.showAdvanced === 'boolean') { this.setState({ showAdvanced: nextProps.showAdvanced }) } }, toggleAdvancedClickHandler: function(e) { this.setState({ showAdvanced: !this.state.showAdvanced }) }, render: function() { return ( <div> <div>Basic stuff</div> <div> <button onClick={this.toggleAdvancedClickHandler}> {(this.state.showAdvanced ? 'Hide' : 'Show') + ' Advanced'} </button> </div> <div style={{display: this.state.showAdvanced ? 'block' : 'none'}}> Advanced Stuff </div> </div> ); } }); 

So, the first time React.renderComponent(MyComponent({}), elem) call React.renderComponent(MyComponent({}), elem) component will be mounted, and the extended div will be hidden. If you click on the button inside the component, it will switch and show. If you need to make the component show the extended div from outside the component, just call the visualization like this: React.renderComponent(MyComponent({showAdvanced: true}), elem) , and it will display it regardless of the internal state. Similarly, if you want to hide it outside, just name it showAdvanced: false .

An added bonus to the above code example is that calling setState inside componentWillReceiveProps does not cause another rendering cycle, as it catches and changes state before render is called. Take a look at the docs here for more information: http://facebook.imtqy.com/react/docs/component-specs.html#updating-componentwillreceiveprops

Do not forget that calling renderComponent again on the already mounted component does not mount it again, it simply responds to the props component props and responds, then makes changes, runs the component life cycle and rendering functions and makes it the dominant magic.

+7
source

Revised response in the comment below.


My initial incorrect answer:

The componentWillUpdate lifecycle function will execute when a new state or attribute is received. Here you can find the documentation: http://facebook.imtqy.com/react/docs/component-specs.html#updating-componentwillupdate

If, when calling an external setState you set showAdvanced to true in componentWillUpdate , you should get the desired result.

EDIT: Another option is for the setState external call setState include showAdvanced: true in a new state.

0
source

Source: https://habr.com/ru/post/1202388/


All Articles