React Component Initialize State from Props

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



Leave a reply



Submit