未捕获的TypeError:无法读取undefined(reactjs)的属性'props'(非常简单)

问题描述 投票:1回答:2

我按照这个关于redux的初学者教程:textvid

一切都有效,但增量按钮除外。单击增量按钮时出现此错误:

未捕获的TypeError:无法读取undefined的属性'props'

看看会发生什么:gif

当我执行“mapStateToProps”时,为什么会出现该错误?

index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import Test_left from './eo_app.jsx';
import { Provider } from 'react-redux';
import { createStore } from "redux";

const initialState = {
    count: 21
};

const reducer = (state = initialState, action) => {
    console.log('reducer', action);

    switch (action.type) {
        case 'INCREMENT':
            return { count: 55 };
        default:
                return state;
    }
};

const store = createStore(reducer);


const App = () => (
  <Provider store={store}>
    <Test_left />
  </Provider>
);

ReactDOM.render(<App />, document.getElementById('target'));

//// store.dispatch({type: 'INCREMENT' }); this will work as expected

eo_app.jsx

import React from 'react';
import { connect } from 'react-redux';


class Test_left extends React.Component {
    constructor(props) {
        super(props);
    }

    increment () {
    this.props.dispatch({ type: 'INCREMENT' }); // <== ERROR IS RAISED HERE
  }

    render() {
        console.log('props:', this.props)
        return (
                <React.Fragment>
                    <h1> WE GOT RENDERED </h1>
                    <h1>{this.props.count}</h1>
                    <button onClick={this.increment}> Increment </button>
                </React.Fragment>
        )
    };
}

const mapStateToProps = state => ({
    count: state.count
})

export default connect(mapStateToProps)(Test_left);
javascript reactjs redux react-redux
2个回答
2
投票

编辑:

实际上有两个问题:

首先,您需要将increment函数绑定到类本身。这是一个常见的“陷阱”,你可以在这里阅读 - https://reactjsnews.com/es6-gotchas

第二个是,使用react-reduxconnect函数,你需要将redux dispatch函数映射到prop。这是通过你在connect调用中传递的第二个函数完成的:mapDispatchToProps

你的看起来像是这样的:

const mapDispatchToProps = dispatch => ({
    handleClick: () => dispatch({ type: 'INCREMENT' })
});

通过这两个更改,您的组件将会是这样的

class Test_left extends React.Component {
    constructor(props) {
        super(props);

        // Bind `increment` to this class's scope
        this.increment = this.increment.bind(this);
    }

    increment () {
        // Use newly created prop function to dispatch our action to redux
        this.props.handleClick();
    }

    // ...
}

const mapStateToProps = state => ({
    count: state.count
});
const mapDispatchToProps = dispatch => ({
    handleClick: () => dispatch({ type: 'INCREMENT' })
});

export default connect(mapStateToProps, mapDispatchToProps)(Test_left);

1
投票

当你执行:this.props.dispatch时,它将调用与connect映射的dispatch。但是你没有发送地图:

export default connect(mapStateToProps)(Test_left);

因此,将以前的代码替换为:

export default connect(mapStateToProps, mapDispatchToState)(Test_left);

现在,为mapDispatchToState定义函数并在那里调用dispatch。


我忘记提到的关键问题是确保绑定this,因为当你调用一个方法时,this将是未定义的。或者,您可以指定public class method

increment = () => { // now, this will be accessible

PS:请参阅this post为什么需要使用地图调度而不是直接调度它。有意义的是不要将连接映射与直接调度混合。

© www.soinside.com 2019 - 2024. All rights reserved.