Using forceUpdate instead of setState in React? - javascript

If I have a react component, and I just set its class variables, ie
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.numberElements = 20;
this.color = 'red';
}
render() {
...
}
}
Can't I just call this.forceUpdate() to issue a re-render (whenever I update my class variables) instead of maintaining a state and calling setState?. Or is it bad to do that, and if so, why?

forceUpdate() is actually useful in scenarios like the one you're describing.
From the docs:
By default, when your component’s state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate().
The caveat, however, is that it will skip shouldComponentUpdate(), so you're not getting the optimization benefit.
Also, using forceUpdate() "bypasses" the proper lifecycle, making your code less straight-forward and possibly harder to understand and maintain.
It is therefore recommended to use state and props when possible.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().

Related

React Native: shouldComponentUpdate() not preventing render() from being called

I have a React Native component where I want to prevent the render() method from being called.
class A extends Component {
shouldComponentUpdate() {
return false;
}
render() {
return(...)
}
}
Returning false in shouldComponentUpdate should prevent render() from being called, but it doesn't. Is there something I'm doing wrong?
Indeed, it prevents a rerender but not the initial rendering. This is documented here.
Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.
and
shouldComponentUpdate() is invoked before rendering when new props or state are being received. Defaults to true. This method is not called for the initial render or when forceUpdate() is used.
Hence, if you return false, then you only prevent a rerendering on state changes.
you can try use hooks useMemo or useCallback https://reactjs.org/docs/hooks-reference.html
to choose what you want to update

Why I am getting the old state values after the props change

I just want to understand why in the application I have following situation, below is my constructor of class component:
constructor(props) {
super(props);
this.state = {
tableAlerts: props.householdAlerts,
initialAlerts: props.householdAlerts
}
console.log('householdAlerts', props.householdAlerts)
}
in render function I have:
const { householdAlerts } = this.props;
My issue is that in constructor I got empty array, but in render funtion I have the data. Is it possible to get the data in constructor?
This is a very bad pattern when using the class component. You are ignoring any props updates when you copy the value into state. to manage it:
It requires you to manage two sources of data for the same variable: state and props. Thus, you need to add another render each time your prop change by setting it into state (don't forget to test on equality from prev and next values to avoid being in an infinite loop).
You can avoid setting the state each time your props change by using the getderivedstatefromprops lifecycle method.
So the recommendation is: just use the props; do not copy props into state.
To learn more why you shouldn't, I highly recommend this article.
It is not recommended to set your initial component state in the constructor like so because you gonna lose the ability to use { setState } method after to update this property/state.
The best practice is indeed to refer directly to the prop with { this.prop.householdAlerts }, and keep the state usage for local (or in child components} cases.
if anyhow you want to store props in component state for some reason, call it in lifeCycle -
componentDidMount() {
const { tableAlerts, initialAlerts } = this.props;
this.setState({ tableAlerts, initialAlerts });
}
Hagai Harari is right. Nevertheless, your actual problem seems to be that during your initial rendering the array is empty. Can you ensure that the array has some items, when your component is rendered for the first time?
First rendering -> calls constructor
<YourComponent householdAlerts={[]} />
Second rendering -> updates component
<YourComponent householdAlerts={[alert1, alert2, alert3]} />
If you want initial state to have the prop value.Try something like this with 'this' keyword
constructor(props) {
super(props);
this.state = {
tableAlerts: this.props.householdAlerts,
initialAlerts: this.props.householdAlerts
}
console.log('householdAlerts', props.householdAlerts)
}

Passing props to a component through state

Prefix:
I am working with react-native, and am wondering the best practice for passing props down from a parent to a child component. I have tested this on my android device only.
Question:
From my understanding it is possible to pass values to a component through the use of props, ie:
<myComponent myProp="some data" />
and it can be referenced in my myComponent using this.props.myProp. Would it be bad practice (or will it even work) to create my state object in the constructor like so:
constructor(props){
super(props);
this.state = {
myStateProp: this.props.myProp
};
}
which could then be called in that component as this.state.myStateProp. I am relatively new to react-native and am trying to learn as much as I can. I have tried it in several use cases with varying results, and am uncertain as to the behavior. Thank you for your input!
There are few good reasons to do this. It's generally considered an anti-pattern because components should be stateless wherever possible.
If what you're trying to do is control the component by passing in props and using as state, I would suggest holding the state in the parent component and then passing any changes back up the chain via props, using a callback.
For example
ComponentOne {
this.state = { colour:red }
handleColourChange(val){
this.setState({ colour: val })
}
return <ComponentTwo changeColour={this.handleColourChange} colour={this.state.colour} />
}
Then imagine in ComponentTwo we have a button and you want to change colour:
<button onClick={this.changeColour(blue)}>Change to blue</button>
This way your child component remains stateless, and is controlled by its parent. this.props.colour will change in the child automatically.

When should a react component be declared as a function, and not a class?

I'm unsure of when to declare react components as simple standalone functions as opposed to the regular class myComponent extends Component syntax. To use an example from React's docs (located here):
The following is referred to as a "component"
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
While it appears to merely be a function and is declared like any regular old function. Then in the next paragraph, the following is ALSO defined as a component, and looks more like the way I think a component should look:
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {temperature: ''};
}
handleChange(e) {
this.setState({temperature: e.target.value});
}
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input
value={temperature}
onChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
What is the difference between these two "components"? Is the first example actually a component if it doesn't inherit from the Component class and isn't being created with React.createClass? I would appreciate somebody explaining this distinction since I couldn't find an answer anywhere in the docs.
When you don't need to use the lifecycle methods and the component isn't stateful you can declare the component as a function. Component lifecycle methods like componentWillMount() and componentDidMount() only can be used if the component is a class that extends Component.
Calculator must be specified as a class-based component because it is dependent upon internal component state i.e. this.setState({...}). Functional components, also known as stateless components do not have a backing instance, thus they are unable to maintain local state in the same way.
Personally, I always try to write functional components as they are arguably easier to test due to their nature of consuming props and returning a tree of ReactElement instances. I will only convert a component to be class-based if it will:
need to manage its own presentation-based state i.e. not applicable to the state of the entire application
benefit from lifecycle methods as a means of improving performance through restricted re-rendering
require references to child ReactElements or DOM nodes via refs
There are two complementary docs from Facebook that explain this quite well:
https://facebook.github.io/react/docs/components-and-props.html
https://facebook.github.io/react/docs/state-and-lifecycle.html
TL;DR a "component" is primarily responsible for representing some DOM. Depending on how your application is organized, your component may or may not need to maintain its own state or have access to the lifecycle methods like componentDidMount or render. In the case that you do need these features, your component should be a class that inherits from React.Component. Otherwise, you can likely get away with writing your component as a plain old function.
If the functional way is more preferred instead of creating classes you could use higher-order components utility called recompose, it has lifecycle HOC.
Small example:
const NewComponent = lifecycle({
componentWillMount() {
this.props.onEnterScreen();
},
})(Component)

ReactJS: adding my own props to another component

Is it possible (or even a good idea) to add my own props to another React component, like:
<SomeCustomComponent myOwnParam={handler}>
As mentioned by Tyrsius, it really depends on the implementation of SomeCustomComponent. If the component does not use the myOwnParam prop anywhere, passing it won't accomplish anything. On the other hand, some React components might use JSX spread attributes to reference props not directly enumerated in the code.
As an example, the following implementation of SomeCustomComponent would pass your myOwnParam prop down to its child div:
class SomeCustomComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
var {customComponentProp, ...other } = this.props;
return (
<div customComponentProp={customComponentProp} {...other}></div>
);
}
}
So again, it depends on the implementation of SomeCustomComponent what will happen.
See Transferring Props documentation for more details: https://facebook.github.io/react/docs/transferring-props.html
This won't cause an error, but unless SomeCustomComponent is looking for this prop nothing will be done with it. It is possible for a component to loop over its props, so this could be a usable strategy, but I am not sure what you would do with it. You couldn't define anything but iteration logic over properties that you don't know in advance.

Categories

Resources