状态更改后,react-redux组件未重新呈现

时间:2020-09-29 16:30:10

标签: javascript reactjs redux react-redux

状态更改后,我的react-redux组件之一未重新呈现。我希望选中该复选框后才能启用选择。但这不会发生。仅当我在页面上的其他位置单击另一个触发重新渲染的组件时,所有内容才会达到我的预期。我究竟做错了什么?我将不胜感激。

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
    }
}

1 个答案:

答案 0 :(得分:1)

最好不更改state.updates,您可以执行以下操作:

const objects = { ...state.objects };
if (objects.select) {
  delete objects.select;
} else {
  objects.select = true; //set it truthy
}
return {
  ...state,
  objects,
};

工作示例:

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>