score:312
componentwillreceiveprops is depcricated since react 16: use getderivedstatefromprops instead
if i understand correctly, you have a parent component that is passing start_time
down to the modalbody
component which assigns it to its own state? and you want to update that time from the parent, not a child component.
react has some tips on dealing with this scenario. (note, this is an old article that has since been removed from the web. here's a link to the current doc on component props).
using props to generate state in
getinitialstate
often leads to duplication of "source of truth", i.e. where the real data is. this is becausegetinitialstate
is only invoked when the component is first created.whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.
basically, whenever you assign parent's props
to a child's state
the render method isn't always called on prop update. you have to invoke it manually, using the componentwillreceiveprops
method.
componentwillreceiveprops(nextprops) {
// you don't have to do this check first, but it can help prevent an unneeded render
if (nextprops.starttime !== this.state.starttime) {
this.setstate({ starttime: nextprops.starttime });
}
}
score:-1
i think use ref is safe for me, dont need care about some method above.
class company extends xcomponent {
constructor(props) {
super(props);
this.data = {};
}
fetchdata(data) {
this.resetstate(data);
}
render() {
return (
<input ref={c => this.data['name'] = c} type="text" classname="form-control" />
);
}
}
class xcomponent extends component {
resetstate(obj) {
for (var property in obj) {
if (obj.hasownproperty(property) && typeof this.data[property] !== 'undefined') {
if ( obj[property] !== this.data[property].state.value )
this.data[property].setstate({value: obj[property]});
else continue;
}
continue;
}
}
}
score:-1
i came up with the following solution using functional components and the useeffect hook: it works by having the useeffect hook watch the controlling property from props
const { useeffect, usestate } = react
const child = (props) => {
const [bgcolor, setbgcolor] = usestate(props.bgcolor);
const { children } = props;
useeffect(() => {
setbgcolor(props.bgcolor);
}, [props.bgcolor]);
return (
<div style={{ height: "100px", width: "100px", backgroundcolor: bgcolor }}>{children}</div>
)
}
const parent = (props) => {
const [childcontrollingprop, setchildcontrollingprop] = usestate(props.childcontrollingprop);
const { title } = props;
const inputref = react.createref();
return (
<>
<input ref={inputref} type="text" onchange={() => setchildcontrollingprop(inputref.current.value)}/>
<child bgcolor={childcontrollingprop}>{title}</child>
</>
)
}
$(document).ready(() => {
reactdom.render(
<parent title="title" childcontrollingprop="blue"/>,
document.queryselector("#root")
);
})
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<div id="root"></div>
score:0
it's quite clearly from their docs:
if you used componentwillreceiveprops for re-computing some data only when a prop changes, use a memoization helper instead.
use: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
score:0
use memoize
the op's derivation of state is a direct manipulation of props, with no true derivation needed. in other words, if you have a prop which can be utilized or transformed directly there is no need to store the prop on state.
given that the state value of start_time
is simply the prop start_time.format("hh:mm")
, the information contained in the prop is already in itself sufficient for updating the component.
however if you did want to only call format on a prop change, the correct way to do this per latest documentation would be via memoize: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
score:0
the data source of the form must be based on user input, in the case that the user has entered, any situation resulting in the update of the subcomponent, will trigger componentwillreceiveprops or getderivedstatefromprops operation, at this time, the value after comparison is certainly not equal, after the execution of setstate, the value of the user input will be changed, is not this a mistake?
score:4
from react documentation : https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
erasing state when props change is an anti pattern
since react 16, componentwillreceiveprops is deprecated. from react documentation, the recommended approach in this case is use
- fully controlled component: the
parentcomponent
of themodalbody
will own thestart_time
state. this is not my prefer approach in this case since i think the modal should own this state. - fully uncontrolled component with a key: this is my prefer approach. an example from react documentation : https://codesandbox.io/s/6v1znlxyxn . you would fully own the
start_time
state from yourmodalbody
and usegetinitialstate
just like you have already done. to reset thestart_time
state, you simply change the key from theparentcomponent
score:6
// store the starttime prop in local state
const [starttime, setstarttime] = usestate(props.starttime)
//
useeffect(() => {
if (props.starttime !== starttime) {
setstarttime(props.starttime);
}
}, [props.starttime]);
can this method be migrated to class components?
score:11
you probably don't need derived state
1. set a key from the parent
when a key changes, react will create a new component instance rather than update the current one. keys are usually used for dynamic lists but are also useful here.
2. use getderivedstatefromprops
/ componentwillreceiveprops
if key doesn’t work for some reason (perhaps the component is very expensive to initialize)
by using getderivedstatefromprops
you can reset any part of state but it seems
a little buggy at this time (v16.7)!, see the link above for the usage
score:35
there is also componentdidupdate available.
function signatur:
componentdidupdate(prevprops, prevstate, snapshot)
use this as an opportunity to operate on the dom when the component has been updated. doesn't get called on initial render
.
see you probably don't need derived state article, which describes anti-pattern for both componentdidupdate
and getderivedstatefromprops
. i found it very useful.
score:43
the new hooks way of doing this is to use useeffect instead of componentwillreceiveprops the old way:
componentwillreceiveprops(nextprops) {
// you don't have to do this check first, but it can help prevent an unneeded render
if (nextprops.starttime !== this.state.starttime) {
this.setstate({ starttime: nextprops.starttime });
}
}
becomes the following in a functional hooks driven component:
// store the starttime prop in local state
const [starttime, setstarttime] = usestate(props.starttime)
//
useeffect(() => {
if (props.starttime !== starttime) {
setstarttime(props.starttime);
}
}, [props.starttime]);
we set the state using setstate, using useeffect we check for changes to the specified prop, and take the action to update the state on change of the prop.
score:56
componentwillreceiveprops
is being deprecated because using it "often leads to bugs and inconsistencies".
if something changes from the outside, consider resetting the child component entirely with key
.
providing a key
prop to the child component makes sure that whenever the value of key
changes from the outside, this component is re-rendered. e.g.,
<emailinput
defaultemail={this.props.user.email}
key={this.props.user.id}
/>
on its performance:
while this may sound slow, the performance difference is usually insignificant. using a key can even be faster if the components have heavy logic that runs on updates since diffing gets bypassed for that subtree.
score:92
apparently things are changing.... getderivedstatefromprops() is now the preferred function.
class component extends react.component {
static getderivedstatefromprops(props, current_state) {
if (current_state.value !== props.value) {
return {
value: props.value,
computed_prop: heavy_computation(props.value)
}
}
return null
}
}
Source: stackoverflow.com
Related Query
- Updating state on props change in React Form
- Props not updating when redux state change in React Hooks
- React Child Component Not Updating After Parent State Change
- Updating state with props on React child component
- How to change props to state in React Hooks?
- React shouldComponentUpdate() is called even when props or state for that component did not change
- Component not updating when I change the props that I pass to it in React
- react is not updating functional component state on input change
- React updating state in two input fields from form submission
- React Child with useEffect() not updating on Parent State Change
- In React componentDidUpdate, can props and state change at the same time?
- Updating C3 charts on props change with React
- Functional Component in React is not updating on props change
- Updating Child Component Via Change of Props from Parent in React
- Updating state on route change with React Redux
- React UI not updating on state change
- React Component not updating with state change
- React Redux: Getting Props And Updating State
- useContext not updating on state change in React
- REACT + REDUX: on redux state change mapStateToProps updating state but view is not rendering as per new state
- react redux updating state on input change
- React - change state when props are changed
- React updating UI after a change in Props feeded to useReducer
- React update child's props after parent's state change
- React child component not updating when props change
- React Hooks - Updating state using props without event handlers
- Updating React child component after state change
- react state not updating on input change
- React form props to state
- Why won't the form state visibly change within the submit button using react form hook?
More Query from same tag
- How to link 'from outside' into Navigator (for example from a global footer)
- React - avoid dropdown to close when you develop the accordion inside the dropdown
- Is there a way to access global state in createSlice?
- Footer overlapping content when trying to make it stay at the bottom of the page
- How do I refresh my component when clicked on tab on bottomTabNavigator in React Native, in React Navigation v3?
- How to insert parentheses in an eval statement to order operations in JavaScript?
- Why won't my nested React components render?
- React: Does it make sense to pass the whole state to another component?
- Handling input change for API call in React.JS
- http-only cookie + token : double job?
- div background not full size, only size of text
- Getting Select Value Using React
- passing data from a react based component to vanilla js class
- Accessing array with Hooks and useState
- React Material UI Grid Horizontally Align Items for Containers With Different Number of Items
- TypeError: Cannot read property 'name' of undefined - Fetching data from restcountries API
- How to activate a single div using React.js and setActive?
- How to set a JSON object from local.storage using setState with React Hooks
- Populate list items from json in React component
- React (Facebook): managed state of controlled checkboxes
- Filtering objects based on the value of an array of objects
- How to write a middleware in nextjs for serverside
- Rendering an array/object in React
- How to place the newline character inside tool tip in react bootstrap?
- Pass variable to another component and display it in ReactJS
- Use string as JS file that declares a react component
- React useEffect onClick Refetch Data - Change Params
- Issue using certbot with nginx
- Prevent div-overlapping only on window resize (w/ Styled Components)
- How to perform Send 'Typing indicator in Botframework v4 chat application using React.js?