score:153
useState
hooks function argument is being used only once and not everytime the prop changes. You must make use of useEffect
hooks to implement what you would call the componentWillReceiveProps/getDerivedStateFromProps
functionality
import React,{useState , useEffect} from 'react';
const Persons = (props) => {
const [nameState , setNameState] = useState(props)
useEffect(() => {
setNameState(props);
}, [props])
return (
<div>
<p>My name is {props.name} and my age is {props.age}</p>
<p>My profession is {props.profession}</p>
</div>
)
}
export default Persons;
score:-1
I believe the problem indicates an attempt to use one conceptual variable or set of variables to do two different things. For example trying to get props.name
and name
to do the same thing.
So if
const [name, setName] = useState(props.name)
isn't enough and you find yourself trying to force props.name
into state variable name
later in the function then maybe name
is being overloaded. Try setting up another state variable - eg. updatedName
and see if things work better.
The original example doesn't demonstrate this problem since the state variables are never used except in log statements.
If const [name, setName] = useState(props.name)
updated on ever re-render there would be no point in having state variable name
since it would always be the same as props.name
(and further attempts to change it would cause re-render).
score:0
I figured an alternative solution avoiding useEffect
. Instead it uses two useState
's. I put it into a custom hook for you:
export function useStateFromProp(propValue) {
const [value, setValue ] = useState(propValue);
const [propValueState, setPropValueState] = useState(propValue);
if (propValueState != propValue) {
setPropValueState(propValue);
setValue(propValue);
}
return [value, setValue];
}
function MyComponent({ value: propValue }) {
const [value, setValue] = useStateFromProp(propValue);
return (...);
}
The main benefit would be that now the re-render that was normally triggered by the useEffect
happens before any child components are re-rendered. so this would be faster.
Disclaimer: I did not test this yet. I did some googling and found this supporting article: https://pretagteam.com/question/in-react-hooks-when-calling-setstate-directly-during-render-is-the-rerender-guaranteed-to-run-before-the-render-of-children
score:0
If you need to calculate state from props and other state without additional re-renders, consider:
a) Using useMemo
hook.
const Component = ({ name }) => {
const [surname, setSurname] = useState('');
const fullName = useMemo(() => {
return name + ' ' + surname;
}, [name, surname])
...
}
b) Calcuating inside render if it is not very heavy:
const Component = ({ name }) => {
const [surname, setSurname] = useState('');
const fullName = name + ' ' + surname;
...
}
c) For hard cases where you need to compare prev props and should be able to update state from another place you can use refs, though it doesn't look good:
const Component = ({ name }) => {
const prevNameRef = useRef()
const derivedState = useRef();
if (prevNameRef.current !== name) {
derivedState.current = ...
prevNameRef.current = name;
}
// some other place
derivedState.current = ...
}
score:1
import React, { useState, useEffect } from "react";
const Persons = props => {
// console.log(props.name);
const [nameState, setNameState] = useState(props);
console.log(nameState.name);
console.log(props.name);
useEffect(
() => {
if (nameState !== props) {
setNameState(props);
}
},
[nameState]
);
return (
<div>
<p>
My name is {props.name} and my age is {props.age}
</p>
<p>My profession is {props.profession}</p>
</div>
);
};
export default Persons;
As per the Hooks react document, all the time when any props is update or any update in component is there then useEffect will be called. So you need to check the condition before updating useState and then update your value so that it continuously doesn't do re-rendering
score:7
For that, you need to use the useEffect
so your code looks like.
As you want to avoid to re-render again if pros didn't change then you have to check first on useEffect and then set the props to current variable.
import React, { useState, useEffect } from "react";
const Persons = props => {
// console.log(props.name);
const [nameState, setNameState] = useState(props);
console.log(nameState.name);
console.log(props.name);
useEffect(
() => {
if (nameState !== props.name) {
setNameState(props.name);
}
},
[nameState]
);
return (
<div>
<p>
My name is {props.name} and my age is {props.age}
</p>
<p>My profession is {props.profession}</p>
</div>
);
};
export default Persons;
score:16
This general idea can be put into hook:
export function useStateFromProp(initialValue) {
const [value, setValue] = useState(initialValue);
useEffect(() => setValue(initialValue), [initialValue]);
return [value, setValue];
}
function MyComponent({ value: initialValue }) {
const [value, setValue] = useStateFromProp(initialValue);
return (...);
}
score:31
The props
value in useState(props)
is used only during the initial render, further state updates are done with the setter setNameState
.
In addition, there is no need for useEffect
when updating derived state:
const Person = props => {
const [nameState, setNameState] = useState(props.name);
// update derived state conditionally without useEffect
if (props.name !== nameState) setNameState(props.name);
// ... other render code
};
From React docs:
[...] you can update the state right during rendering. React will re-run the component with updated state immediately after exiting the first render so it wouldn’t be expensive.
[...] an update during rendering is exactly what
getDerivedStateFromProps
has always been like conceptually.
In essence, we can optimize performance by getting rid of an additional browser repaint phase, as useEffect
always runs after the render is committed to the screen.
Working example
This is a contrived example illustrating above pattern - in real code you would read props.name
directly. See the React blog post for more appropriate derived state use cases.
const Person = props => {
const [nameState, setNameState] = React.useState(props.name);
// Here, we update derived state without useEffect
if (props.name !== nameState) setNameState(props.name);
return (
<p>
<h3>Person</h3>
<div>{nameState} (from derived state)</div>
<div>{props.name} (from props)</div>
<p>Note: Derived state is synchronized/contains same value as props.name</p>
</p>
);
};
const App = () => {
const [personName, setPersonName] = React.useState("Lui");
const changeName = () => setPersonName(personName === "Lukas" ? "Lui" : "Lukas");
return (
<div>
<Person name={personName} />
<button onClick={changeName}>Change props</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
Source: stackoverflow.com
Related Query
- How to sync props to state using React hooks : setState()
- how to set state array using react hooks
- How to get the changed state after an async action, using React functional hooks
- How do I correctly add data from multiple endpoints called inside useEffect to the state object using React Hooks and Context API?
- How to update the state of nested json object in react using hooks
- How to type props in a React PureComponent using hooks in TypeScript?
- How to pass state value to a callback function using React Hooks
- React Hooks - Updating state using props without event handlers
- How to update the state in different mobile screens using React Hooks
- How to pass state from class components to global state when using react hooks for global state management
- How to render component conditionally when leaf value of global state changes using react hooks
- how to change state by setState in React hooks
- How to call API and stores results in a state when a form submit is clicked using react hooks
- How to setState in DE-structured objects using react hooks
- How to update the state in functional component using React Hooks
- How to update state if I have props coming from parent component in React Hooks
- How to store initial toggle state in localStorage using React hooks
- How to define a state as object in react using hooks
- How to keep the state updated using React hooks and observable design pattern?
- How to update state for device width using Hooks in react
- How do I increment the count of a selected index of state object using setState method given by useState hook in my react application
- How to update state from two different handlers using useReducer hooks from React
- Why is my state beeing updated before i call setState with React Hooks and how do i fix the disabled mouse pointer?
- How to update state itself using react hooks
- How to pass value of state in a function in react using hooks
- How remove item from redux state using react hooks
- How to send props to state other components in React Hooks
- How to set a JSON object from local.storage using setState with React Hooks
- How would I re-render the list everytime the state changes for this text filter using react hooks
- How to change cart icon state using React Hooks
More Query from same tag
- React props undefined on receiving
- Get onClickItem to Link to a URL or a route in react-simple-tree-menu
- Can I create a custom component library NPM package out of Material UI?
- object type of html markups that passed as javascript function parameters
- export data as csv in react
- JavaScript new formData().append is not working for uploaded files
- React React-router Invariant Violation: replaceState(...) Error
- redux-sagas callback (aka sagas and setState)
- Using APIs in a React Template
- Ant design Tabs onClick function
- Typescript | Typescript is missing 27 Props, when extending formikProps on IProps
- getStaticProps in HOC not working in Next.js
- Trouble sending File from React frontend with Fetch to Express 4 API
- Page refreshes after the dropdown value is selected in React
- Next.js - axios in getInitialProps returns 404
- Custom hook is not a function React
- Functional component with hooks results in "cannot read property map of undefined"
- react-chartjs integration error. Cannot read property 'xLabels' of undefined
- How to use React Router properly? I am trying to push the state of my application to another page when the user logs in
- LocalStorage doesn't save on refresh
- How to use clsx in nested components in React
- React loop through map and display components
- useContext returning udefined
- Rendering UI in React Router 4
- How to route a details page of a photo when clicked in React?
- Update redux form field from a callback
- Click on Name - shows phone Number React
- React Leaflet marker rotation
- Issue with componentWillReceiveProps in React
- Alternative to eval for converting a string to an object