How to cause the component to re-render after an ajax request - javascript

Rerendering same component inside one function in ReactJs. I'm adding comment and now after that I want to rerender the same component. Can anyone help?
commentPost() {...
axios.defaults.headers.common['Authorization'] = getToken;
axios.post(apiBaseUrl+'v1/comments/post-comment',input)
.then(function (response) {
console.log("Comment Post",response);
//here I want to rerender this component itself
})
.catch(function (error) {
console.log(error);
});...

There are two things that you can do to cause the same component to render
First: Update a state of the current component using the setState method.
setState() will always lead to a re-render unless
shouldComponentUpdate() returns false. If mutable objects are being
used and conditional rendering logic cannot be implemented in
shouldComponentUpdate(), calling setState() only when the new
state differs from the previous state will avoid unnecessary
re-renders.
Second: You can call forceUpdate in case you do not want to update any state of the current component. You can call it like this.forceUpdate().
Calling forceUpdate() will cause render() to be called on the
component, skipping shouldComponentUpdate(). This will trigger the
normal lifecycle methods for child components, including the
shouldComponentUpdate() method of each child. React will still only
update the DOM if the markup changes.
Assuming that you are performing an async request from which you are getting a response you would want to update the component's state with the data that you got and hence setState would be the way forward for you

Related

What's the best solution for re-rendering child components on props change in React?

I have a parent component that fetches data in componentDidMount() hook. The state is setState()-d with this data. Then I pass the data to the child components as props and set their state based on these props. On the first render the props will be undefined because componentDidMount() hasn't executed yet. So, the child components get undefined props and the state is created with them. When the data fetches in componentDidMount() new props are passed to the child components, but the state is already created with undefined props and nothing changes. So, I am aware of two solutions now:
Use componentWillRecieveProps(). But this is now deprecated.
Use stateless child components. Pass the data to them as props from
the parent component and don't set a state(use the data from props),
and when the parent does a setState() in componentDidMount(), this
will cause a re-render to child components with new props and
everything works.
Now, what if I want to have stateful child components? I can't use the second method, and the first one is deprecated. What is the best solution to accomplish this?
static getDerivedStateFromProps(props, state)
is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
This method exists for rare use cases where the state depends on changes in props over time.
static getDerivedStateFromProps(nextProps, prevState){
if(nextProps.someValue!==prevState.someValue){
return { someState: nextProps.someValue};
}
else return null;
}
For more details enter link description here
You can read this blog post.
In short a better approach would be to use fully uncontrolled component with key.
Add a key to the child component based on data. If the data changes, the key changes and child component will re-mount.
Provide data as props to the child, use this props as default state of child component.
Here is a sandbox example
Consider using the replacement for componentDidReceiveProps, getDerivedStateFromProps, if you have state within a component which is informed by the values of the props it receives.
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

Why React keep componentWillReceiveProps and shouldComponentUpdate methods both?

when i use react ,i find these two life cycle are too similar, componentWillReceiveProps receive nextProps as argument, shouldComponentUpdate receive nextProps and nextState as arguments, so i think shouldComponentUpdate can do the same thing and more, why react keep componentWillReceiveProps method, i wonder what's difference between these two methods
They have two different roles and execute on different situations:
shouldComponentUpdate will be called every time a prop or something in the state changes (or React think that has changed). It's function is to determine if the component should re-render by returning a boolean: true if the component should re-render (this is the default return value), or false if it shouldn't.
You can access the current and next state and props, to compare and decide if it really should re-render or not. You should not use this method for other reason.
On the other side, componentWillReceiveProps will only be called if the props changed (or seem to have changed). If only the state changes, this method won't be called.
Also, this won't decide if the component should re-render. You can use this method to, for example, change some state, or make an API call.
Check out these links:
componentWillReceiveProps: https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/component_will_receive_props.html
shouldComponentUpdate: https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/using_should_component_update.html
componentWillReceiveProps - as the function name states this is called whenever new props will be passed to the component and you can trigger an action depending on the new prop state
shouldComponentUpdate - is a filter function which decides if the component tree should be re-rendered. This function can serve as an additional filter where you change are happening which don't require a re-render
More info here

React - updating state during render produces errors

I'm new to React and am trying to update the state of a parent component from the child everytime an onChange action happens. The onchange action comes from an input box that when letters are typed it updates the state of searchInputVal with the value of what has been typed. I have a parent <App/> component with the following properties and states here:
updateSampleFilteredState(filteredSamples) {
this.setState({
samples: filteredSamples
});
},
getInitialState () {
return {
samples:allSamples,
searchInputVal:""
}}
I pass the properties and states down to a child component here:
updateNewSampleState(filteredSamples){
return (
this.props.updateSampleFilteredState(filteredSamples)
)
}
render() {
const filteredSamples = this.props.samples.filter(sample => {
return sample.sampleFamily.toLowerCase().indexOf(this.props.searchInputVal.toLowerCase()) !== -1;
});
this.updateNewSampleState(filteredSamples);
return <div className="samples-container-inner-styling">
{
filteredSamples.map((sample) => {
return (...
Before I added the line this.updateNewSampleState(filteredSamples); the child component would render out the filtering just fine but obviously not update the state of sample with the new filtered state. When I the line this.updateNewSampleState(filteredSamples); to execute the function in the component to set the new state I get a list of re-occuring errors that eventually make my app crash. The errors say something about an anti pattern. I'm not sure how else to update the state?
You should't be updating the state from the render function, and you are facing the reason why that's a bad way to do things. Every time you call the setState the component re-renders, so if you call it inside the render function it will be called again and so on... You should ask yourself why are you calling that function there. I guess you could just do it in the onChange function you are using for the input.
As already mentioned by #César, setting the state in the renderer doesn't make sense, since setting the state triggers a rerender of the component, so you basically get something like an infinite render loop.
Given that you are computing filteredSamples only from the props, you could compute that state in the constructor:
The constructor is the right place to initialize state.
However, note the following when deriving state from props in the constructor:
It's okay to initialize state based on props if you know what you're doing. [...]
Beware of this pattern, as it effectively "forks" the props and can lead to bugs. Instead of syncing props to state, you often want to lift the state up.
If you "fork" props by using them for state, you might also want to implement componentWillReceiveProps(nextProps) to keep the state up-to-date with them. But lifting state up is often easier and less bug-prone.

re-render when update this.props.location.query.somequery Reactjs

render() function will fire when this.props.location.query.someQuery updated. But I do not want re-render the component when updated query.
The way I updated query is following:
this.props.location.query.someQuery = otherValue;
hashHistory.replace(this.props.location);
Take a look at the react lifecycle.
You should implement a method called shouldComponentUpdate().
Use this as an opportunity to return false when you're certain that the transition to the new props and state will not require a component update.
This method will be called each time React thinks your component should update, if you don't want it to re-render under certain conditions, check for those conditions and then return false in this function.

How to fetch data when a React component prop changes?

My TranslationDetail component is passed an id upon opening, and based on this an external api call is triggered in the class constructor, receiving data to the state, and this data being displayed on TranslationDetail.
//Routing:
<Route path="/translation/:id" component={TranslationDetail}/>
//Class:
class TranslationDetail extends Component {
constructor(props){
super(props);
this.props.fetchTrans(this.props.params.id);
}
This all works fine if I enter the url manually. In case I'd like to use react-router e.g. for displaying the next item like below the url does change, but the api call is not triggered, and the data will remain the same.
<button
type="button"
onClick={() =>
browserHistory.push(`/translation/${Number(this.props.params.id)+1}`)}>
Next
</button>
Please bear in mind that I'm a total beginner. The reason why this is happening is I believe that the constructor is run only once, thus no further api call is triggered.
How can I solve this?
Do I need to listed to props and call a function on change? If yes, how?
Constructor is not a right place to make API calls.
You need to use lifecycle events:
componentDidMount to run the initial fetch.
componentDidUpdate to make the subsequent calls.
Make sure to compare the props with the previous props in componentDidUpdate to avoid fetching if the specific prop you care about hasn't changed.
class TranslationDetail extends Component {
componentDidMount() {
this.fetchTrans();
}
componentDidUpdate(prevProps) {
if (prevProps.params.id !== this.props.params.id) {
this.fetchTrans();
}
}
fetchTrans() {
this.props.fetchTrans(this.props.params.id);
}
}
From React 16.3 and onwards componentWillMount, componentWillUpdate and componentWillReceiveProps are deprecated.
You can use static getDerivedStateFromProps and return a new state based on changes on props.
You don't have access to your this objects like props, so you cannot compare nextProps with your current props by nextProps.sth !== this.props.sth. You can compare you prevState value with nextProps and return new value of state.
Make sue you add UNSAFE_ to your current componentWillMount and the other deprecated lifecyle methods for now.
Use componentWillMount to get the data and set the state.
Then use componentWillReceiveProps for capturing update on the props.
You can check the Component Specs and Lifecycle.
I would use the render method. If the data is not loaded I would render a loader spinner and throw the action that fetch de data. For that i usually use the stores. Once the store has de data from the api, mark the data as loaded, throw an event and let the component get the data from the store, replacing the loader spinner with your data representation.

Categories

Resources