I have the following, super-simple Component:
export default class Editor extends Component {
constructor(props) {
super(props);
this.state = { field: "Some Initial Text" };
this.handleChangeField = this.handleChangeField.bind(this);
}
handleChangeField(e) {
this.setState({field: e.target.value});
}
render() {
return (
<div>
<input type="text" name="word" value={this.state.field} onChange={this.handleChangeField} />
{this.state.field}
</div>
);
}
}
It just has a field. The field can be edited by the user. Depending on what the user clicks on in a sibling-component, the above component will receive a prop called fieldValue which will then be what's shown in the input field. Since the user should be able to edit this input field, I cannot simply put the prop into the input-field directly, but use state. So I initialise the components state from the prop.
However, this prop might change even after the component is initialised. That is, it will not only be an initial value, but might change during runtime, depending on what the user clicks on in the sibling-components.
How would I solve something like this in React 16.3, with ComponentWillReceiveProps being deprecated? I have tried looking into GetDerivedStateFromProps, but I don't fully understand how to use it.
I wouldn't go for trying to sync uncontrolled component with controlled component, as the logic can get crazy when the component scales.
With that said, if you really want to track prop changes and update state accordingly you could use componentDidUpdate but make sure you got some valid conditions before updating the state.
Here is a running example:
class Editor extends React.Component {
state = { field: this.props.defaultValue };
componentDidUpdate(prevProps) {
const { defaultValue } = this.props;
if (prevProps.defaultValue !== defaultValue) {
this.setState({ field: defaultValue });
}
}
handleChangeField = (e) => {
this.setState({ field: e.target.value });
}
render() {
return (
<div>
<input type="text" name="word" value={this.state.field} onChange={this.handleChangeField} />
{this.props.defaultValue}
</div>
);
}
}
class App extends React.Component {
state = { value: 'A default value' }
handleChange = ({ target }) => this.setState({ value: target.value })
render() {
const { value } = this.state;
return (
<div>
<h3>App </h3>
<input type="text" value={value} onChange={this.handleChange} />
<hr />
<h3>Editor</h3>
<Editor defaultValue={value} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With