How to set dynamic value in a useState from parent component - reactjs

I have a parent component that sends a useState string to its child component.
I can access that useState but I want to set it in another one but I am not able to do that because it rerenders all the time and it breaks the app.
Child component:
const Child = ({firstValue}) => {
const [secondValue,setSecondValue) = useState(firstValue);
}
First, it takes the default value but it never updates it.
I want to update it automatically when the firstvalue changes its value.
I have tried to set it by setSecondValue(firstValue) but it runs in a infinite rerender loop and it breaks.
I also tried with: const [secondValue,setSecondValue) = useState(...secondValue, {value: firstValue});
Also it is worth to mention that I need it to be updated onload, not in any onClick or onChange function.

need to use useEffect to update secondValue when firstValue changes
useEffect(() => {setSecondValue(firstValue)}, [firstValue])

Related

rerender in react to get a new name everytime I refreshed?

why this code give me infinite loop?
import { useState, useEffect } from 'react';
import './style.css';
import { faker } from '#faker-js/faker';
export default function App() {
const data = faker.name.firstName();
const [name, setName] = useState(data);
useEffect(() => {
setName(faker.name.firstName());
}, [name]);
return <div>{name}</div>;
}
https://stackblitz.com/edit/react-ts-6ept5o?file=App.tsx
I want a new generated name using faker everytime i refreshed the page.
Well there's several problems here. Firstly, React state isn't persisted when you refresh the page. To do that you'd have to web storage or some library to help store when changing/refreshing the page. So you don't need an effect here nor to worry about getting new fake data on refresh, you will.
Also, when a functional component re-renders, the entire function gets run again. So this: const data = faker.name.firstName(); gets run every time you render. If you want to use it as an initial state, use the function argument to useState which runs it once on page load: useState(() => faker.name.firstName());
Finally, in regards to the infinite loop, your effect has name as a dependency, but inside it you also set name state. So you're getting a loop.
Component renders:
-> effect runs, setting name state
-> set state triggers re-render with new name
-> new name triggers effect, since name is a dependency
-> effects sets name state to new value
-> set state triggers re-render
and so on. But in this case, you don't actually need an effect at all, given reasons mentioned above
You have a useEffect that runs every time name changes.
When it runs, you're setting name to a new value.
This changes name and triggers the useEffect again.
When it runs, you're setting name to a new value.
This changes name and triggers the useEffect again.
And so on...
You need to understand how useEffect works.
you have set name in useEffect array dependency. So everytime the component renders name changes, as name changes your component renders again and goes into infinity loop. So you leave empty array:
const [name, setName] = useState("");
useEffect(() => {
setName(faker.name.firstName());
},[]);
return <div>{name}</div>

Why do we need to use setValue in UseState?

So, React has UseState hook, and we should use it like this.
const [value, setValue] = useState(0);
And if we want to change a value, it should be written like this:
const increase = () => {
setValue(value + 1)
}
Why it's not possible to write it like this? Why we need setValue?
const increase = () => {
return value + 1;
}
I understand that it just doesn't work, but I couldn't find an explanation why it is like that.
The useState hook returns a function to update the state. Using setValue(value) method, you can get the previous(or old) state value to update the state.
On the other hand, without useState when you tries to increment the value, the value will not change because the react rendered the component only once and since there is no state change it won't get re-rendered, the value will remain at 0.
You can see here in details : https://dev.to/aasthapandey/why-to-use-usestate-in-react-pkf
Answer is simple...! The state variable is directly linked to rendering your page. The state variable of useState hook is read only for the component to render it in the below return statement which renders the JSX.
The setValue() function not only changes the state value, but will also trigger the react to re-render the DOM which has already being painted on the browser.
Well that's a difference between an ordinary HTML page & a React App. React provides amazing framework to re-render the page automatically after the you alter the state using the setValue() fucntion

How to access data of Child Component from parent component in react js

I am doing a project where i have a toast function which implements toast there i call the function of fetching data from api and updating my state so that whenever i click the update feed button fetching data from api function called, updation of state and toast of success appears. Now the question is i have a component of categories post displays seperate category post inside of all post component which has the function to display toast, how could i pass the updated state,fetching data from api function from child component that is category post component to parent component that is all post component to implement toast for category component.
If I understand your question correctly -- at a high level, you're trying to figure out how to update a state variable of a parent component from within a child component. Easiest way would be with the useState hook, and then by passing the setState function to the child component.
const ParentComponent = () => {
const [state, setState] = useState([])
useEffect(() => {
// logic that will be executed every time the state variable changes
}, [state])
return <ChildComponent setState={setState} />
}
const ChildComponent = ({setState}) => {
const handleClick = () => {
setState((currentState) => currentState.concat(1))
}
return <Button onClick={handleClick} />
}
Edit: To answer your question from the comment -- a few things to point out here:
You can pass a value to useState which will be the starting value of the variable. In our example, it's an empty array
setState has access to the current state, so you can push a value to an array with this syntax: setState((previousState) => previousState.concat(val))
useEffect is a hook which is invoked whenever there's a change in the value of the dependency (or dependencies) passed in the second argument. So by including state in its dependency array, we can execute whatever logic we want every time the value of the state variable changes
I would also recommend looking into useMemo. It similarly allows you to have aspects of your component logic that are re-executed only when values of certain variables change. For example:
const ParentComponent = () => {
const [state, setState] = useState([])
useEffect(() => {
// logic that will be executed every time the state variable changes
}, [state])
const renderCards = useMemo(() => {
return state.map(val => <SomeOtherComponent val={val}/>)
}, [state])
return (
<div>
{renderCards}
<ChildComponent setState={setState} />
</div>
)
}
By wrapping the function inside renderCards in the useMemo hook, the evaluated result is "memoized". And so it won't be executed on every render, unless the variable in the dependency array changes.
Passing down setState to a child component in order to trigger a re-render in the parent component is straightforward when it's an immediate child. If the child component is nested deeper, or there are multiple components that need to react to a change in a variable (e.g. light/dark mode) -- that's when you want to look into a state management tool like Redux or Context.
There are two ways I can think of to achieve what you are trying to do here, i.e. get the child component's state in a parent component.
You can make use of refs. You should be familiar with React hooks to use this approach. The documentation is really good.
You can also make use of a global state using either Redux or Context.

React: How to pass state to child component and call function in child to use this state

I am implementing a component in functional components where there are several other child components in it passing data to each other. I need to pass data from parent to child component and call some function there to use it.
In class componenets we use componentdidupdate but could not understand how to do in functional component.
One idea is to use useEffect hook but could not do with it.
Im going to take a stab here, because we dont have context or code to go with.
useEffect accepts a dependency array to which it will react when a value or object reference changes
const ChildComponent = (props) => {
const {
valuePassedFromParent
} = props;
const actionFunction = (value) => {
//perform some tasks with value passed from parent when it changes
}
//this is similar to componentDidUpdate, but it reacts to changes in valuePassedFromParent though props since its in the useEffect dependency array
useEffect(() => {
//do something with valuePassedFromParent
actionFunction(valuePassedFromParent);
},[valuePassedFromParent]);
return (
<div>
</div>
)
}
You cas use useEffect to reproduce the behavior of componentdidupdate like this :
const [myState,setMyState] = useState();
useEffect(() => {
...
},[myState]);
The function use effect will run every time myState will be updated, like componentdiduptate would have do.
In your case, the state is given by the parent component if I understand well, so just replace the myState in the array dependency by the state given through the prop of your child component.

How to use useState hook to set value within FormDataConsumer

I am having to set a const value using useState hook in FormDataConsumer. This is necessary because the value of the const can only be gotten within FormDataConsumer. This const value will be used as a prop to another component. The problem I am having is the error message below. What is the best way to do this? Thanks in advance
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
//const initialized here
const [outletsList, setOutletsList] = useState([]);
//the place where the const must be set
<FormDataConsumer>
{({ formData, ...rest }) => {
//console.log(`formData: ${JSON.stringify(formData)}`)
//console.log(`rest: ${JSON.stringify(rest)}`)
let s = GetOutletsBySalesRep({
distributorkey: formData.distributorid,
salesrep: formData.salesrep,
});
**setOutletsList(s);**
}}
</FormDataConsumer>
The error you get is because of the way React itself works - you update a state variable which makes the component to rerender and on each render you set the state again ... so you end up in an endless loop.
To escape it you should either set a condition upon which the state will be updated e.g.
if(outletsList.length === 0) setOutletsList(s);
Or use a reference to save the result through the useRef hook updating it's current property because this operation doesn't trigger a rerender.
const outletsListRef = useRef();
...
outletsListRef.current = s;
Although not sure why you would need to save it and not rerender the component.

Resources