React State Change Not Causing Re-Render

react setState() not triggering re-render

Here you go: Codesandbox demo.

You should first make a shallow copy of the array you want to modify. Then set that array as the new state. Then it re-renders the component and you are able to filter like you want.

  const sort = (event) => {
console.log(event);
//shallow copying the state.
const newArr = [...sortedPlans];

//modifying the copy
newArr.sort((a, b) => {
return b[event] - a[event];
});
console.log(newArr); //results here are correctly sorted as per event

//setting the state to the copy triggers the re-render.
return setSortedPlans(newArr);
};

React - State change of parent does not cause re-rendering of child when passed down as props?

You have the following snippet in your Child constructor:

this.state = {
value: this.props.value
}

The above only sets the Child state once, before the component is mounted. Therefore, none of your increments/decrements push through from your parent to child.

The best solution to your problem is to simply keep the state in your parent component, and only pass down a function that can update it.

Try this:

class App extends React.Component {
constructor() {
super()
this.state = {
myState: 0
}
this.handleClick = this.handleClick.bind(this)
this.updateState = this.updateState.bind(this)
}

updateState(newState) {
this.setState(newState);
}

handleClick() {
this.setState((previousState) => ({myState: previousState.myState + 1}), () => console.log(this.state.myState))
}

render() {
return (
<div>
<Child value={this.state.myState} update={this.updateState}/>
<button onClick={this.handleClick}>This updates the state of App (parent)</button>
</div>
)
}
}

class Child extends React.Component {
constructor(props) {
super(props)
this.randomize = this.randomize.bind(this)
}

randomize() {
this.props.update({myState: Math.random() * 100})
}

render() {
return(
<div>
<h1>My value is {this.props.value}</h1>
<button onClick={this.randomize}>This changes the state of Child</button>
</div>
)
}
}

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

React state changes, but component doesn't re-render

React uses Object.is() equality (referential) to determine whether state has been updated. We should not directly mutate state, as if you're sending it the same reference, it just won't know.

You can either send an entirely new copy, as you did in your working version, or use the syntax that takes an updater function to set state from current state.

Why is useState not triggering re-render?

You're calling setNumbers and passing it the array it already has. You've changed one of its values but it's still the same array, and I suspect React doesn't see any reason to re-render because state hasn't changed; the new array is the old array.

One easy way to avoid this is by spreading the array into a new array:

setNumbers([...old])

How can I prevent re-render after state changed in React Hooks?

You can use useMemo hook.

It prevents specific jsx contents from rerendering, even when the state that those jsx contents/components use get updated.



const App=()=>{
// you can only memoize parts that do not require use of the updated variable in this case. It means that Header cannot be memoized.

const mainArea = React.useMemo( () => <MainArea/>, [] );

const footer = React.useMemo( () => <Footer/>, [] );

const [showMenu,setShowMenu]=useState(false)


return(
<>

<Header showMenu={showMenu} setShowMenu={setShowMenu}/>

{mainArea}

{showMenu ? <Menu/> : null}

{footer}

</>
)

}


EDIT:

Does the really need the state of the showMenu? Or we can only pass the setShowMenu to it?
If so, then you can also memoize the Header component into memo chunk like:

const header = React.useMemo( () => , [] );



Related Topics



Leave a reply



Submit