How change react local component state with global state if conditional...? - reactjs

my English is not good but I try, to explain my problem.
I am new in react, I need to know how can I change local component state with global component if conditional is met..

It is difficult to answer because you have no code in your question. You will find you will garner a better response by providing what you have tried. However I will guess that what you need to do is setState according to a condition that you define.
setState(updater[, callback])
From the docs:
setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses.
For example in psuedo code:
if (predicate) {
this.setState((prevState, props) => {
return {key: value};
});
}
You can start by reading the docs here for more on setState.

Related

React substitute for componentDidReceiveProps

I am creating a chat app and I have a component called ChatBox. ChatBox subscribes to a WebSocket when the user clicks on a chat channel. Right now, this is done in the constructor. The issue is that I now need to let the user change channels, but constructor is not called when the props change. I could use componentDidUpdate, but I would have to compare my props against my old props on every render, which is very inconvenient.
TL; DR: I need to do something when my props get changed. I found a method called componentDidReceiveProps which fits my situation perfectly! But sadly React says that the method is bad practice, and they made it deprecated:
One of the biggest lessons we’ve learned is that some of our legacy
component lifecycles tend to encourage unsafe coding practices ... These lifecycle methods have often
been misunderstood and subtly misused
My question is: what is the correct way to produce the same behavior?
Use componentDidUpudate. Check if the relevant prop changed, and if so, update the socket or do whatever else is needed.
componentDidUpdate(prevProps) {
if (this.props.channel !== prevProps.channel) {
// do stuff
}
}
but I would have to compare my props against my old props on every render, which is very inconvenient.
Yes, you do need to check that the right prop changed. You'd have to do that with componentWillReceiveProps also.
This can be reproduced using the useEffect hook. The if you set the dependency array to contain the prop(s) you are looking for, then it will run only when that prop changes.
To do so, you'll need to convert it to a functional component instead of a class-based component.
Example:
import React from 'react'
Function ComponentName(props){
React.useEffect(() => {
// Code inside here will run when anything in the dependency array changes
}, [prop.propName]) //<---Dependency array. Will watch the prop named "propName" and run the code above if it changes.
return (
//Your JSX
)
}

React, componentWillReceive lifeCycle Hook not being invoked (on passing props)

I was trying to pass props both in App component (The root Component) and then to Header component from App itself.
I have used Life Cycle Hooks upto componentWillReceiveProps() in both App and Header Component.
componentWillMount(), render(), componentDidMount() are getting executed in both the Components in an expected order.
However, componentWillReceiveProps() is not executed at all even on passing props. This is a unExpected behaviour, since componentWillMount() was executed normally!
I shall be extremely thankful to know why is this happening ! Thank you :)
Kindly check the code sample from the below link:
https://codesandbox.io/s/r092xkpwjp
Please Note: Question has been updated, and it shows both scenarios now, new props being passed (in Header Component which works fine now) and no new props being passed as was previously the case in the question (in App Component which still shows why things were working unexpectedly).
I don't see why you expect your components to be updated as the The props being passed to them always stay the same and no new props have been passed to these at all, but generally you should use componentDidUpdate(prevProps, prevState).
componentWillReceiveProps() only gets invoked when the props passed to them are new props, different from the previous values. In the question this was not happening.
Note: The question has been updated now for it to work properly.
Also consider managing the state by static getDerivedStateFromProps(props, state), i.e.:
static getDerivedStateFromProps(props, state){
// just return the state
return {
isLoading: false,
money: props.money
}
}
- it's executed on init + on updates.
As stated in the official documentation (see https://reactjs.org/docs/react-component.html) the
componentWillReceiveProps()
lifecycle method is deprecated and should be avoided.
The reason why it is never called is that, to help user avoid it, React developers renamed it
UNSAFE_componentWillReceiveProps()
You should however avoid it, since they plan to deprecate that method
1.The main reason why the componentWillReceiveProps() was not being invoked was because my props passed to Header Component were not changing at all, I have been passing the same props again and again. And componentWillReceiveProps() gets executed only when the props being passed are different each time.
This is what my Header component looked at the time of asking this question.
<Header
menus={["home", "about", "services", "blog"]}
/>
The Header Component had only the menus prop as an array (at the time of asking this question) and no event was updating this menus prop , that's the reason why my
componentWillReceiveProps() was never invoked/called in the Header Component.
Note: To simply the things I now passed another prop to Header Component, and started to test my code on this prop instead of working with the array menus prop.
<Header
menus={["home", "about", "services", "blog"]}
prop={this.state.prop}
/>
And I am making my state.prop to update using an event handler:
// Dynamically sending Props
handlePropSending = () => {
this.setState({
...this.state,
prop: this.state.prop + 1
});
};
And as I am clicking on the button 'Sending Props to Header', the new props are sent to Header Component and our componentWillReceiveProps is being called and executed succefully.
And same was the issue with componentWillReceiveProps in the App Component
ReactDOM.render(, rootElement);
Since I was adding money prop (money={9199}), there actually is no Parent Component available for money prop to update it's value (which we could have passed to the App Component for it to invoke its componentWillReceiveProps method).
NOTE: The code is updated now and there are event handlers now to make sure the props keep updated and now the componentWillReceiveProps() method is indeed being successfully invoked.
componentWillReceiveProps demonstrated along with other life Cycle Hooks
LIKE THEY SAY :) ALL IS WELL THAT ENDS WELL :)

ReactJS - componentWillReceiveProps uses

I started to learn ReactJS I would like to know what are the scenario to use componentWillReceiveProps? what is the purpose for using it?
Currently i'm using props without it, is there any impact ?
In cases where you want to take action in child component in response to props change, componentWillReceiveProps was supposed to the right candidate. Example of it is when you have a user component which calls and API to fetch the user details based on an ID that is provided by its parent and anytime the prop ID changes, you would want to trigger the API call again and re-render the updated view.
However, componentWillReceiveProps is called on every parent re-render and not just prop change, so while you are using it, you must provide a conditional check between previous and currentProps like
componentWillReceiveProps(nextProps) {
if(nextProps.id !== this.props.id) {
//API call goes here
}
}
However from v16 onwards, its discouraged to use componentWillReceiveProps and instead its usage is split into componentDidUpdate which is where you can make API calls and getDerivedStateFromProps or memoized functions or key updates in order to make state change based on prop change.
Please check componentWillReceiveProps vs getDerivedStateFromProps for more details
If your component accept some props and if on change of that props you would like to do some business logic or state change, componentWillReceiveProps is the lifecycle method where this logic should go, as every time props changes componentWillReceiveProps is called.

componentDidUpdate called twice every route change

In my application i have a HomePage component which has navlinks in it. the route for this component is <Route to="/browse/:item" exact component={HomePage} />. so the component has a navigation bar with NavLink links to "sub routes" of it. for example a NavLink that leads you to /browse/featured or
/browse/new and i added to this component the lifecycle method componentDidUpdate() to just console.log("UPDATED HOMEPAGE") and whenever i click a NavLink this happens:
i tried to use shouldComponentUpdate with the nextProps and nextState params to see if indeed the state or props are changed (something that will cause a re-render) but they stay the same.
Thanks in advance for your help.
EDIT:
the code is on github https://github.com/idanlo/spotify-test-frontend
components that have the problem that i have seen are AlbumView and HomePage
ANOTHER EDIT:
this is a console.log() of the two updates happening, each one displaying the props before and after the update. on the first update you can see that the url is different so the update is supposed to happen but on the second update nothing is different, everything is the same (in the state everything is the same too)
Usually there are multiple calls because of changes made to the state. Check other files to make sure that no actions that modify the state are initially called. Even though you check for differences for nextProps, the variable that changes might not be in props.
I suspect that Navlink's internal implementation uses setState with an updater function which is the source of this duplicate log
I found that when I update state with an updater function then componentDidUpdate gets fired twice!
However when I pass an object to setState - componentDidUpdate is fired only once.
setState(updater[, callback])
example:
incrementScore = () => {
this.setState(prevState => ({
score: prevState.score + 1
}));
};
VS
setState(stateChange[, callback])
example:
this.setState({quantity: 2})
I guess it's because
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.
read about setState on React Docs

Reactjs, I need some understanding of this.setState and prevState

componentWillReceiveProps(nextProps) {
// Check to see if the requestRefresh prop has changed
if (nextProps.requestRefresh !== this.props.requestRefresh) {
this.setState({loading: true}, this.updateData);
}
}
As far as my understanding goes, this lifecycle hook is called when a Component's properties are updated by the parent.
This piece of code checks if the requestRefresh property is different (one to update and one that it currently has)
Now what i dont understand is this , this.updateData);
why is this with the setState method. Please help me understand
Secondly where does prevState come from and which lifecycle hook can update it
the setState method can be called with a callback as its second parameter, mainly to handle operations which need to be done when the state is fully updated.
In your example this.updateData is the callback.
setState's first argument is also a function, with the signature (prevState, props) => stateChange, this is allowing you to get access to the previous state when performing updates.
You may want to check the official doc for further details :
https://reactjs.org/docs/react-component.html#setstate
The React maintainers discourage the use of componenetWillReceiveProps.
From the React docs:
It is recommended that you use the static getDerivedStateFromProps lifecycle instead of UNSAFE_componentWillReceiveProps. Learn more about this recommendation here.
To answer your question: prevstate is the previous state, so it is the state of your component before new props are received which in turn might chnage the new state. You can also hanlde prevstate in the static getDerivedStateFromProps method:
static getDerivedStateFromProps(nextProps, prevState)
getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. It should return an object to update state, or null to indicate that the new props do not require any state updates.

Resources