【问题标题】:Simple Redux-React trying to updating state by this.props.dispatch简单的 Redux-React 尝试通过 this.props.dispatch 更新状态
【发布时间】:2019-09-28 20:40:17
【问题描述】:

当我点击复选框时,this.props.dispatch({type: "addPreferredChecked"});会导致此错误:

TypeError: 无法读取未定义的属性 'dispatch'

我将非常感谢您的帮助,同时也让您知道这个项目是在带有 React 和 Redux 的 Typescript 中运行的。

作为 Redux 新手,我只是想在单击复选框时简单地将 HTML 复选框选中属性从 true 更改为 false,反之亦然。我的演示组件具有成功调用 handleCheckedChange 函数并传入预期数据的 onclick 逻辑。这是经过测试并且可以正常工作的。

但是当我运行时:this.props.dispatch({type: "addPreferredChecked"}); 来自我的handleCheckedChange()

我收到此错误:

TypeError: Cannot read property 'dispatch' of undefined
./src/containers/App.tsx.App.handleCheckedChange [as onChange]
src/containers/App.tsx:64

64 | this.props.dispatch({type: "addPreferredChecked"});

我曾尝试放入 mapDispatchToProps 函数,然后将其添加到 connect 语句,但随后 props 不再在 Chrome React Developer Inspect 中显示 dispatch()。

我还成功地从减速器所在的 index.tsx 中运行了store.dispatch({type: "addPreferredChecked"});

我对 index.tsx 中的 redux 代码也很有信心,因为我已经成功设置了 store、connect 和 mapStateToProps 以从 redux 存储中读取字段。

Index.tsx 的减速器:

  function reducer(state = initialState, action) {

     switch ( action.type ) {
        case "unCommunicationChecked":
          return {
            CommunicationChecked: false
          };
        case "unIdMyDeviceChecked":
          return {
            IdMyDeviceChecked: false
          };
        case "unPreferredChecked":
          return {
            PreferredChecked: false
          };
        case "addCommunicationChecked":
          return {
            CommunicationChecked: true
          };
        case "addIdMyDeviceChecked":
          return {
            IdMyDeviceChecked: true
          };
        case "addPreferredChecked":
          return {
            PreferredChecked: true
          };  
        default:
          return state;
      }
  }

const store = createStore(reducer);

// store.dispatch({type: "addPreferredChecked"}); successful results



  App.tsx:
    class App extends React.Component <Props, State> {

      handleCheckedChange(newCheck: boolean, Checktype: string) {

        if (newCheck === true) {
            Checktype = "un" + Checktype;
        } else if (newCheck === false) {
            Checktype = "add" + Checktype;
        } else {
            console.log("Bad handleCheckedChange call");
        }        
        this.props.dispatch({type: "addPreferredChecked"});

      }            

【问题讨论】:

  • 你在构造函数中绑定了handleCheckedChange吗?如果您没有,this 关键字将不会指向正确的位置。
  • 我目前没有使用构造函数,因为我正在使用 redux 存储状态并在容器组件和表示组件之间传递 props 数据,就像这样
  • 我将 props 传递到我的 export const EmailCopy = (props) => { return ( ..... 我的 html 看起来像 我这样做对吗?

标签: reactjs typescript redux


【解决方案1】:

Redux 工作的最低要求如下:

  1. Reducer。你有一个function reducer(state = initialState, action)。但它应该被纠正。见下文。
  2. Connect你要存储的组件

    export default connect(
        (state) => state, // Selects which state properties are merged into the component's props
        (dispatch) => {
            return { 
                addPreferredChecked: () => dispatch({type: "addPreferredChecked"}),
                addIdMyDeviceChecked: () => dispatch ({type: "addIdMyDeviceChecked"})
            }
        })(App);
    

addPreferredCheckedaddIdMyDeviceChecked 被称为action creators

  1. 您应该使用 Provider 为 App 组件提供对 store 的访问权限

    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
    )
    

您的reducer 也不正确。 Reducer 应该总是return new state,但是你的reducer 只返回改变的部分状态。

正确的减速器看起来像

function reducer(state = initialState, action) {
    switch ( action.type ) {
        case "unCommunicationChecked":
            return {
                ...state,
                CommunicationChecked: false
            };
       // And so on. Add ...state to all cases

Working example

【讨论】:

  • 我添加了:export default connect(mapStateToProps, (dispatch) => { addPreferredChecked: () => dispatch({type: "addPreferredChecked"}) }) (App); & 引用它: this.props.dispatch({addPreferredChecked}); addPreferredChecked 正在作为标签访问,this.props.dispatch 无法找到它。我尝试通过返回代码将其注入道具,但随后我得到了同样的错误:TypeError:无法读取未定义的属性'dispatch'。我错过了什么?
  • 我的语法不正确吗?我假设这是 action: dispatch({type: "addPreferredChecked"}) 并且我不需要 action.js 文件,对吧?感谢月亮和回来的帮助。
  • 我添加了工作示例来回答。(codesandbox.io/s/7k8vo39r3q) 和一些澄清
  • 您的工作示例非常出色,非常有帮助,非常感谢!我终于让调度工作了,我能够将 addPreferredChecked 注入我的道具。我现在还剩一件。我正在使用一个调用演示组件(EmailCopy)的容器组件(App)。该应用程序具有连接和还原意识,而电子邮件副本具有带有 onclick 事件的复选框 HTML。
  • 我一直在通过在容器和演示组件之间绑定我的道具
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-27
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 2016-02-29
相关资源
最近更新 更多