One of my react-redux components is not re-rendering after state change. I want the select to become enabled after the checkbox is checked. But that doesn't happen. Only if I click somewhere else on the page on another component that triggers re-rendering, everything becomes as I expected. What am I doing wrong? I would be grateful for any help.
class Select extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<input type="checkbox" onClick={this.props.toggleSelect}/>
<select disabled={ !Object.keys(this.props.syncObjects).includes("select") }>
// some options
</select>
</div>
)
}
}
const mapDispatchToProps = {
toggleSelect
}
const mapStateToProps = state => {
return {
syncObjects: state.json.objects
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Select);
// reducer file
const initialState = {
objects: {}
}
export const myReducer = (state = initialState, action) => {
switch (action.type) {
case TOGGLE_SELECT:
if (Object.keys(state.objects).includes("select")){
const new_state = {...state}
delete new_state.objects["select"]
return new_state
}
else {
return {
...state,
objects: {
...state.objects,
'select': ''
}
}
}
default:
return state
}
}
// actions.js
export function toggleSelect() {
return {
type: TOGGLE_SELECT
}
}
Best to not mutate state.updates, you can do the following:
const objects = { ...state.objects };
if (objects.select) {
delete objects.select;
} else {
objects.select = true; //set it truthy
}
return {
...state,
objects,
};
Working example:
const { Provider, connect } = ReactRedux; const { createStore, applyMiddleware, compose } = Redux; const initialState = { objects: {}, }; //action types const TOGGLE_SELECT = 'TOGGLE_SELECT'; // actions.js function toggleSelect() { return { type: TOGGLE_SELECT, }; } const reducer = (state = initialState, action) => { switch (action.type) { case TOGGLE_SELECT: const objects = { ...state.objects }; if (objects.select) { delete objects.select; } else { objects.select = true; //set it truthy } return { ...state, objects, }; default: return state; } }; //creating store with redux dev tools const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( reducer, initialState, composeEnhancers( applyMiddleware(() => (next) => (action) => next(action) ) ) ); class Select extends React.Component { render() { return ( <div> <input type="checkbox" onClick={this.props.toggleSelect} checked={Object.keys( this.props.syncObjects ).includes('select')} /> <div> select enabled: {String( Object.keys(this.props.syncObjects).includes( 'select' ) )} </div> <div> select enabled (simpler example): {String(Boolean(this.props.syncObjects.select))} </div> </div> ); } } const mapDispatchToProps = { toggleSelect, }; const mapStateToProps = (state) => { return { syncObjects: state.objects, }; }; const App = connect( mapStateToProps, mapDispatchToProps )(Select); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script> <div id="root"></div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.