Reputation: 79
I am writing an application that consists of a large grid of squares. Each square (or cell) maintains its own state. Clicking on an individual cell changes its colour (the Cell uses useState())
I want to have a single reset button that will set all the cells back to their initial state i.e. coloured white.
I can't work out how to get this single button to change the state of all the cells. The number of cells can vary (depending on the layout size selected) be between 121 and 529 of them.
Any advice greatfully accepted!
Upvotes: 2
Views: 1660
Reputation: 6582
you can use a context
and wrap all your cells
in context.provider
and then in your cells
useEffect
hook listen for the result of context if it changed you can change the state of each cell to its initial something like this:
//in resetContext.js
const ResetContext = React.createContext();
const useResetContext = () => React.useContext(resetContext);
//in resetContextProvider.js
const ResetContextProvider = () => {
const [reset, setReset] = React.useState(false);
const providerValue = {reset, setReset}
return (
<ResetContext.Provider value={providerValue}>
//put your Cells in here
</ResetContext.Provider>
)
}
// in Cells
const initialValue = 'something';
const Cell = () => {
const [cellState, setCellState] = React.useState(initialValue)
const resetObj = useResetContext();
React.useEffect(() => {
if(reset){
setCellState(initialValue)
}
}, [resetObj])
return <div /> // or whatever your components are
}
Upvotes: 1
Reputation: 281626
The simplest solution is to actually change the key of the common parent of the grid element that forces all the children to remount and this resetting all their states
Sample demo
class Child extends React.Component {
state = {
counter: 0
}
render() {
return (
<div>{this.state.counter}<button onClick={() => this.setState(prev => ({counter: prev.counter+1}))}>Increment</button></div>
)
}
}
class App extends React.Component{
state = {
elemKey: 0,
}
render() {
return (
<React.Fragment>
<div key={this.state.elemKey}>
{[...Array.from(new Array(10))].map((item, index) => {
return <Child key={index} />
})}
</div>
<button onClick={() => {this.setState(prev => ({elemKey: (prev.elemKey + 1)%2}))}}>Reset</button>
</React.Fragment>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"/>
Upvotes: 5