I am developing a web page using React, and have some questions about the "Lifting Stat Up" example (and I paste the link for complete code of it here for quick reference), which is inconsistent with what I encountered in my own project.
My question is about this part:
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
while user input new values, the celsius will be re-calculated (triggered by a callback function in TemperatureInput which calls handleCelsiusChange, and then render is triggered), and passed as one of props to TemperatureInput. But inside the definition of TemperatureInput, why componentWillReceiveProps is not defined? In my practice, if the props is assigned in constructor only, it will not be updated automatically if value changed. As the document said, it will not create a new element but just update the existing one for performance. If there is no new instance is created, the constructor would not be invoked, so the this.props will not be updated without a componentWillReceiveProps function.
All these above is consistent to my practice, but not to the example. Why componentWillReceiveProps is not required in the example to make this.props updated?
The constructor in this case is not doing anything special with the props, it is just calling the React.Component constructor with super() which is what it would do anyway. If it was setting some state from props for example, then you would need a componentWillReceiveProps, as you would need to update the state when the props change.
When the component gets new props, the constructor is not invoked again, as it is already an instance, instead react updates the props on the component instance, and calls the render() again, so the props in render() will be the updated props. If you had a componentWillReceiveProps defined, it will be called before the call to render();
Related
I read in an article that if you have some code like:
class Parent extends Component {
render() {
return (
<Child
onClick={() => console.log('You clicked!')}
/>
);
}
}
Child will be re-rendered every time Parent re-renders, even if there's no change in its props, only because the onClick function is inline and so it creates a new reference on every render.
However, even after moving that function outside of render(), Child re-rendered.. so what am i missing here?
In addition, that article also mentioned that inline functions increases a React app's memory footprint, since a new function reference is created on each render. Is that true? Doesn't JS have some sort of automatic garbage collection?
A couple of things, what you have posted only works for Class components, and as to why it works with Class components is that you are creating a callback function and binding it to the instance of the component, therefore each render of the component, it is the same callback function instance being used.
More reading on this https://www.freecodecamp.org/news/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb/ under "Why don’t we need to bind ‘this’ for Arrow functions?"
For a function component, it's different, there is no class instance, you can use the useCallback hook that will memoize a callback, given a set of dependencies remain the same.
As someone pointed out in the comments you should only really aim to memoize callbacks etc though when they will prevent rerenders of large/deep children
I have heard of getDerivedStateFromProps but it does not work how I want it to.
I have this code:
class App extends Component {
static getDerivedStateFromProps(props, state) {
console.log("Get derived state from props called");
return null;
}
render() {
return (
<button onClick={() => this.setState({})}>Change State</button>
);
}
}
Clicking the button calls getDerivedStateFromProps. This is not what I need. I want a function that is called only when new props are received. When internal state changes, this function should not be called.
I intend to use this in a modal form scenario. When the component receives an object as a prop, the component should translate this object into a form, then place that form into the state. If I use getDerivedStateFromProps, since it is called in every this.setState(), it would not reflect the changes in the form since whenever the user types, a this.setState() is fired, and instead of the changes being set into the state, the initial object is.
Which React lifecycle method should I use?
There are a couple of ways to approach this problem depending on different use cases.
If new props are added, those new props can be checked in the Child component and user defined functions can be called in case the new object exists.
getDerivedStateFromProps(props, state, prevProps) is a static method and this does not exist in the same, which means that you'll have to return a state based on various conditions. That is, let it work on default on most cases. On cases where you want to alter its functionality, place checks and return the modified state.
Hope it answers :)
React has instance property and state property in react in constructor.
Instance property - Its not re-render the view. use to store the value.
State property - Its store and re-render the view.
Apart from above any other reason or difference or when should be use for both instance and state in constructor of React class component?.
Example:
class example extends Component{
constructor(){
this.state = {
name: 'albert'
};
this.name = 'albert';
}
}
When component state changes, it triggers component re-rendering (if it's not set to be ignored in shouldComponentUpdate()).
Changing instance property does not trigger re-rendering.
simple difference for both that is view part rendering.
EX: When State is update the view also update. Sometimes view is need not to reload that time we can store the value in component instance as you mentioned this.name.
Just check with below link to more about state and instance
https://medium.freecodecamp.org/where-do-i-belong-a-guide-to-saving-react-component-data-in-state-store-static-and-this-c49b335e2a00
It depends upon your requirement, which kind of data you are storing within it.
When any state variable is updated, react calls render to make changes in DOM element, so if you want to make any changes in DOM you should use state otherwise instance.
The current best practice is to use local state to handle the state of
your user interface (UI) state rather than data.
from this article
and instance properties when you just want to save some data to use in UI handling, calculations etc.
check this ref react-components-elements-and-instances for futher details
Whenever state is updated, react calls the render() method to update the DOM with required changes, and it should always be updated using setState(). The instance variable will be useful for block level manipulations which would then update the state if required. So if you want to re-render the DOM use state variables, else use instance variables.
My understanding was that PureComponent leverages shouldComponentUpdate() and does a shallow comparison of state and props but I created a little example that operates differently than I expected.
The example app displays a list of people. Each list item has the ability to change its name. Try it out and inspect the code here.
In the parent component, I have a method that looks like this:
updateName(id, newName) {
const { people } = this.state
const idx = people.findIndex(person => person.id === id)
people[idx].name = newName
this.setState({ people })
}
The object that I'm passing back into setState has the same reference as the previous object. In this case, shouldn't this component not update if it's doing a shallow comparison?
Secondly, another part that's unclear, I changed the child component Person from PureComponent to Component and I'm still getting the benefit of only the child that was updated re-rendering (I'm doing a console log on each child render if you want to inspect that). Clearly this is something that React is doing internally to decide for the child whether it should update but I assumed that if the component was re-rendering it would re-render everything.
shouldn't this component not update if it's doing a shallow comparison?
Yep. And it isn't updating. You can see that the App component's render() method does not get called again after the initial render. This means the shallow comparison is working as you expect and the component is (correctly) not updating.
I believe the part that's throwing you off is this line in Person.prototype.handleSubmit():
this.setState({ value: '' })
Since oldState.value !== newState.value, this will trigger a re-render on the modified Person component, regardless of whether Person is a PureComponent or not.
If you take this line out, you will see that nothing updates (the behavior you're expecting).
Clearly this is something that React is doing internally to decide for the child whether it should update.
Nope, the child is setting its own state. The parent-child relationship is irrelevant here. React will update the child directly.
In the future you should try isolating your tests. The reason this confusion occurred is because you were relying on the render() method to determine whether a child received new props. But the render() method is called when a child receives new props AND when a child sets new state.
A better test for this situation would have been checking whether componentWillReceiveProps() is called, thus eliminating state from the picture:
componentWillReceiveProps(newProps) {
console.log('receiving props', newProps)
}
If you plug this into the Person component, you will see that it does not get called. Exactly as you're expecting.
In short, React.PureComponent works exactly as you were thinking.
I am studying the principles of react.
According to some reviews, some people says is better to keep your component stateless, what does it mean?
But other people says, that if you need to update your component, then you should learn how to set your state to the proper state.
I saw this.props / this.setProps and this.state / this.setState and I am confuse with that.
Something I am trying to figure is, how can I update a component by itself and not from a parent component? should I use props or state in this case?
I already read some docs about props and state, what I don't have clear, is: when to use one or another ?
Props vs. state comes down to "who owns this data?"
If data is managed by one component, but another component needs access to that data, you'd pass the data from the one component to the other component via props.
If a component manages the data itself, it should use state and setState to manage it.
So the answer to
how can I update a component by itself and not from a parent component? should I use props or state in this case?
is to use state.
Props should be considered immutable and should never be changed via mutation. setProps is only useful on a top-level component and generally should not be used at all. If a component passes another component a property, and the first component wants the second to be able to change it, it should also pass it a function property that the second component can call to ask the first component to update its state. For example:
var ComponentA = React.createClass({
getInitialState: function() {
return { count: 0 };
},
render: function() {
return <Clicker count={this.state.count} incrementCount={this.increment} />;
},
increment: function() {
this.setState({count: this.state.count + 1});
}
});
// Notice that Clicker is stateless! It's only job is to
// (1) render its `count` prop, and (2) call its
// `incrementCount` prop when the button is clicked.
var Clicker = React.createClass({
render: function() {
// clicker knows nothing about *how* to update the count
// only that it got passed a function that will do it for it
return (
<div>
Count: {this.props.count}
<button onClick={this.props.incrementCount}>+1</button>
</div>
);
}
});
(Working example: https://jsbin.com/rakate/edit?html,js,output)
For and object-oriented programming analogy, think of a class/object: state would be the properties you put on the class; the class is free to update those as it sees fit. Props would be like arguments to methods; you should never mutate arguments passed to you.
Keeping a component "stateless" means that it doesn't have any state, and all its rendering is based on its props. Of course, there has to be state somewhere or else your app won't do anything! So this guideline is basically saying to keep as many components as possible stateless, and only manage the state in as few top-level components as possible.
Keeping components stateless makes them easier to understand, reuse, and test.
See A brief interlude: props vs state in the React docs for more information.
Use state when you know the variable value is going to affect the view. This is particularly critical in react, because whenever the state variable changes there is a rerender(though this is optimized with the virtual DOM, you should minimize it if you can), but not when a prop is changed (You can force this, but not really needed).
You can use props for holding all other variables, which you think can be passed into the component during the component creation.
If you have want to make a multi-select dropdown called MyDropdown for example
state = {
show: true,
selected:[],
suggestions:this.props.suggestionArr.filter((i)=>{
return this.state.suggestions.indexOf(i)<0;
})
}
props={
eventNamespace:'mydropdown',
prefix : 'm_',
suggestionArr:[],
onItemSelect:aCallbackFn
}
As you can see, the objects in the state variable are going to affect the view some way or the other.
The objects in the props are mostly objects which should remain the same throughout the component life cycle. So these objects can be callback functions, strings used to namespace events or other holders.
So if you do want to update the component by itself, you need to have to look into how componentWillRecieveProps ,componentWillUpdate, componentDidUpdate and componentShouldUpdate works. More or less, this depends on the requirement and you can use these lifecycle methods to ensure that the rendering is within the component and not in the parent.