Call custom method on component when props update - reactjs

I have a YouTubeiFrame react component that renders an empty div and then drops the YouTube iframe player in to that div using componentDidMount. All works fine. I have a cueVideo method defined on the component which uses the players
API to cue new videos:
cueVideo(videoId) {
this.player.cueVideoById(videoId)
}
In different places in my app you can click a button or some another action to indicate that you want to play a new video. When you perform this action the 'currentVideo' state is updated via redux and as a result the YouTubeiFrame component receives the new video id as an updated prop.
My question is how to call the cueVideo method above in reaction to the updated prop. I've considered using shouldComponentUpdate to compare this.props.currentVideo with the next props
but concious this method is really supposed to return true/false so the render function can be called. All I want to do is call cueVideo when the currentVideo prop changes - I don't really need to re-render.
What's the best way to do this?

All I want to do is call cueVideo when the currentVideo prop changes - I don't really need to re-render.
When new props are received, React will automatically call render() to update your component. Once all the updates have been flushed to the DOM, React will also call componentDidUpdate() on your component to give you an opportunity to respond to the changes. As the documentation says:
Use this as an opportunity to operate on the DOM when the component has been updated.
I would suggest this is the perfect place to call your code as needed.

Related

What renders a function in React

I have following component:
const RenderJobsTable = props => {some render stuff in here};
And I call that function in another functions render:
<Collapse isOpen={toggleJobTable} id="collapseExample">
<CardBody>
<RenderJobsTable
crawl={props.crawl}
jobs={jobs}
></RenderJobsTable>
</CardBody>
</Collapse>
I noticed that every time I collapse the outer element and toggle it so it gets visible again, the function is called again. What exactly triggers the function to be called in React? Is it when the element is visible? Is if if one of it's parameters changes? Or if parent functions gets changed? If I just toggle the element and I have some call's to a rest service I don't want that to happen all the time. So I need to understand what triggers the call.
Basically, Reacts render method gets triggered almost every time something related to the state of the component changes. From How does React decide when to re render a component?:
A re-render can only be triggered if a component’s state has changed. The state can change from a props change, or from a direct setState change. The component gets the updated state and React decides if it should re-render the component. Unfortunately, by default React is incredibly simplistic and basically re-renders everything all the time.
Component changed? Re-render. Parent changed? Re-render. Section of props that doesn't actually impact the view changed? Re-render.
You can also refer to a similar question's answer.
Related to when to make API calls, I strongly suggest that you read about React component Lifecycle (for example here or here).
TLDR, place your API calls in componentDidMount().

ComponentWillReceiveProps method does not invoke automatically unless there is some API which triggers this through mapStateToProps function

Suppose I have a React class based component named as "ComponentA". Now I have called the action creator (getCategories) inside componentDidMount hook of this component and get its response inside componentWillReceiveProps through mapStateToProps setting up and carrying state inside redux. Now if I switch to "componentB" and trying to get this already setted up state inside componentWillReceiveProps through mapStateToProps of "ComponentB", the componentWillReceiveProps never invoked unless there is an API call which forcing this to invoke. I want to invoke this method of "ComponentB" everytime I switch to this component without API call. Please let me know the correct solution of this problem. Thanks
As per you description, It is hard to resolve your issue, but this is my try.
As you are switching the component, assuming you click some link, you will never get data in componentWillReceiveProps because whenever you are switching the component, that component only go through below process as a newly mounted component.
componentWillMount() -> Render -> componentDidMount().
This is the process for newly mounted component.
The data you want in componentWillReceiveProps will only come when you pass data from parent to child and not when you switch the component.
As you are using redux, and changing some state in one component (ComponentA), you can access the changed state the another component's (ComponentB) ComponentDidMount().

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.

React + Redux: Scrolling a DOM element after state change

New to Redux here, really just looking for a "best practice" answer.
I am building a chat application using React + Redux. My app looks something like this:
3 stateless components for my app container, message list, and input bar
Actions for adding user messages/responses
A reducer that takes in these actions and returns a messages array
Chat middleware which handles a emitting a socket message when then ADD_MESSAGE action is dispatched
So far so good. Everything is working well, however I'm unsure of how/where in this sequence I should be making DOM manipulations. Specifically, I would like to scroll to the bottom of my message-list container whenever my messages state changes.
All I need to fire is something like: messagesListElement.scrollTop = messagesListElement.scrollHeight;, but not sure where the appropriate place to do this is.
You mentioned that all the three components are stateless which means the messages are maintained in redux store which means they are passed as props to the child components. Basically there are five life cycle methods which could get triggered after/before the component gets updated.
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
render()
Now since you want to scroll down after a new message is pushed to the messages state, the best place to do this would be componentDidUpdate()
Why not componentWillReceiveProps - This is the function which will get executed just before a new message is about to be passed in the new props of the component. This is the best place to update your component's state against the new props but since your component is stateless, this is not the right place for scrolling. This could be helpful
Hope it helps :)

How to animate a React component on render?

I am trying to animate a React component that contains data fetched from elsewhere. Placing it in a ReactCSSTransitionGroup worked fine. That is, until I altered the component's render() method to return false until the data has been fetched (to prevent it from being rendered without data).
Now, I guess the component is mounted immediately, at which point the animation classes are added, but only rendered afterwards. Is this thinking correct? How can I get the component to be animated when render returns the actual component?
ReactCSSTransitionGroup activates whenever components are added and deleted to its props.children. Since your component is mounted before you fetch data, nothing will happen after data is fetched (I think this is true even if the component's render() method returns false. Let me know in the comments if that is incorrect)
Here's a solution
Just don't mount the component (in the solution, it's a <div key="1"> tag) until the react class receives the data. Use component states on the parent component to keep track of the state of your asynchronous request.
The ReactCSSTransitionGroup doesn't play nicely with tables as it's default behaviour is to wrap tags with a span element. You can provide it with your own component, but I found the solution quite heavy and complex.
I have a different approach that allows a React component to animate each time its content changes. The animation is continually triggered by toggling between 2 duplicate CSS styles.
Other than the ReactCSSTransitionGroup, another way is to write your own css transitions with an 'enter' class that is added to the component in componentdidmount. Keep in mind that you should change the state in a requestAnimationFrame because otherwise your class would be added in the same event loop as it is mounted, thus wont animate. Here's an example:
https://codesandbox.io/s/zkm5015y1x
Also, more on event loop, a talk by Jake Archibald:
https://www.youtube.com/watch?v=cCOL7MC4Pl0

Resources