React component initialize state from props
It should be noted that it is an anti-pattern to copy properties that never change to the state (just access .props directly in that case). If you have a state variable that will change eventually but starts with a value from .props, you don't even need a constructor call - these local variables are initialized after a call to the parent's constructor:
class FirstComponent extends React.Component {
state = {
x: this.props.initialX,
// You can even call functions and class methods:
y: this.someMethod(this.props.initialY),
};
}
This is a shorthand equivalent to the answer from @joews below. It seems to only work on more recent versions of es6 transpilers, I have had issues with it on some webpack setups. If this doesn't work for you, you can try adding the babel plugin babel-plugin-transform-class-properties
, or you can use the non-shorthand version by @joews below.
How to initialize the react functional component state from props
First you can define it from props (if the prop exist):
const [count, setCount] = useState(activeSym);
And then you can update this value, when prop doesn't have a value immediately (when component rendered):
useEffect(() => {
if (activeSym) {
setCount(activeSym);
}
}, [activeSym])
initialize state before rendering with parents props
According to the React lifecycle docs: Click Here
you can use the following code in your class to update before initial render:
constructor(props) {
super(props);
this.state = {
restaurant: null
};
}
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.restaurant !== nextProps.restaurant) {
return { restaurant: nextProps.restaurant };
}
return null;
}
How can i initialize state by passing props from parent component to child component in ReactJS?
When you initialize the state within the consturctor, updated prop from the parent would not update the child's state.
You'd want to sync the state using getDerivedStateFromProps to keep the internal state up to date with the prop changes. (Do not use componentWillReceiveProps as it is now unsafe).
It's pretty tricky to get it right, so I will refer you to the official documentation, You Probably Don't Need Derived State, with which you can figure out which approach to use for your use case.
Can't initialize state from props
This is happening because the redux store is initialized with an empty object. By the time the redux-form reducer initializes its own initialValues
, the <Timer />
component gets an undefined value of workPeriod
and kicks-off the setInterval(). Here is how I would solve this issue using React Hooks:
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { formValueSelector } from "redux-form";
let Timer = ({ workPeriod, countdownHasStarted }) => {
const [seconds, setSeconds] = useState(0);
const [minutes, setMinutes] = useState();
useEffect(() => {
// first initialize the minutes when the workPeriod is initialized
setMinutes(workPeriod);
}, [workPeriod]);
useEffect(() => {
let interval;
if (minutes) {
interval = setInterval(() => {
console.log("minute state: ", minutes);
if (countdownHasStarted) {
if (seconds > 0) {
setSeconds((sec) => sec - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(interval);
} else {
setMinutes((min) => min - 1);
setSeconds(59);
}
}
}
}, 1000);
}
return () => {
// cleanup function
clearInterval(interval);
};
}, [countdownHasStarted, minutes, seconds]);
return (
<div className="numbers">
<div className="box" id="minutes">
<p>{minutes}</p>
</div>
<div className="box" id="colon">
<p>:</p>
</div>
<div className="box" id="seconds">
<p>{seconds < 10 ? `0${seconds}` : seconds}</p>
</div>
</div>
);
};
Timer = connect((state) => {
const selector = formValueSelector("intervalSettings");
const workPeriod = selector(state, "workPeriod");
return {
workPeriod,
countdownHasStarted: state.countdownHasStarted,
};
})(Timer);
export default Timer;
issue while initialising state using props in ReactJS functional component
Setting useState's initial value is a one-time action (like initializing states in a class constructor) and it won't update itself.
You can make use of a useEffect hook to update it in the Bookmark
component.
useEffect(() => setBookmark(isBookmarked), [id]);
Not initializing state from props
class One extends React.Component {
render(){
return <Two option={name='riaz'} />
}
}
should be
class One extends React.Component {
render(){
return <Two option={{name:'riaz'}} />
}
}
They way you're accessing it tells me that your option
is an object which has a property name
. So you need to also pass it as such.
Also I think @Konstantin Samarin is right in saying to have a proper constructor when dealing with props in class component.
So your constructor will be :-
constructor(props) {
super(props);
this.state = {
name: this.props.option.name
}
}
But this isn't advised by React. You can see the same in the link for docs shared by him.
React.useState does not reload state from props
I've seen almost all the answers to this question promoting a bad pattern: updating state as a result of a prop change inside a useEffect
call. The useEffect
hook is used for synchronizing your React components with external systems. Using it for synchronizing React states can potentially lead to bugs (because re-renders caused by other effects can lead to unintended state updates). A better solution would be to trigger a reconciliation with a key
prop change in the <Avatar />
component from its parent:
// App.jsx
function App() {
// ...logic here
return <Avatar initialUser={user} key={user.id} />
}
// Avatar.jsx
function Avatar({ initialUser }) {
// I suppose you need this component to manage it's own state
// otherwise you can get rid of this useState altogether.
const [user, setUser] = React.useState(initialUser);
return user.avatar ? (
<img src={user.avatar} />
) : (
<p>Loading...</p>
);
}
You can think of that key
prop in this case as the dependency array of useEffect, but you won't be triggering unintended state changes as a result of unexpected useEffect
calls triggered by the component renders.
You can read more about this here:
Putting Props To State
And more info on how useEffect
might be a foot gun, here:
You Might Not Need an Effect
Is it possible to initialize a React component?
You can use a key
to force react to unmount and remount the component. Keys give react additional information about which element from one render corresponds to which element from the next render. If the keys are different, then this tells react they are different elements, even if they have the same type.
const App = () => {
const [gameNumber, setGameNumber] = useState();
const resetGameView = () => {
setGameNumber(prev => prev + 1);
}
return (
<div>
<GameView key={gameNumber} />
</div>
);
}
Related Topics
Angularjs - How to Use $Routeparams in Generating the Templateurl
How to Use Redirect in Version 5 of React-Router-Dom of Reactjs
Get All Attributes of an Element Using Jquery
JavaScript - Get Minutes Between Two Dates
Doesn't JavaScript Support Closures with Local Variables
Redirect a State to Default Substate with Ui-Router in Angularjs
How to Expose Iframe's Dom Using Jquery
JavaScript Associative Array to JSON
Template String as Object Property Name
How to Watch for a Route Change in Angularjs
How to Detect When the Mouse Leaves the Window
Dynamic Function Name in JavaScript
JavaScript Url Decode Function
How to Prevent Caching of My JavaScript File