未处理的拒绝(TypeError):无法读取属性' props'在redux

时间:2017-06-17 13:30:46

标签: reactjs redux react-redux

我在我的应用程序中使用redux,我正在尝试增量和减量。

/actions/index.js

export const INCREMENT = "SCORE_INCREMENT";
export const DECREMENT = "SCORE_DECREMENT";

const scoreAction = {
  increment() {
    return {
      type: INCREMENT
    };
  },

  decrement() {
    return {
      type: DECREMENT
    };
  }
};

export default scoreAction;

/reducers/index.js

import * as actions from "../actions";

const scoreReducer = (state = 0, action) => {
  switch (action.type) {
    case actions.INCREMENT:
      return state + 1;
    case actions.DECREMENT:
      return state - 1;
    default:
      break;
  }
};

export default scoreReducer;

index.js

import { Provider } from "react-redux";
import { createStore } from "redux";
import scoreReducer from "./reducers";

let store = createStore(scoreReducer);

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

App.js

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import RoundedButton from "./RoundedButton";
import { connect } from "react-redux";
import { scoreAction } from "./actions/index";
import * as actions from "./actions/index";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      score: 0
    };
    this.clickitem = this.clickitem.bind(this);
  }

  clickitem(user) {
    var url = "http://localhost:4000/generate-random";
    fetch(url)
      .then(function(response) {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then(function(data) {
        var computer = data.item;
        console.log("------------------------------------");
        console.log(user + computer);
        console.log("------------------------------------");
        if (
          (user === "Rock" && computer === "Scissors") ||
          (user === "Paper" && computer === "Rock") ||
          (user === "Scissors" && computer === "Paper")
        ) {
          console.log("------------------------------------");
          console.log("User won!!");
          console.log("------------------------------------");
          this.props.increment();
        } else if (user === computer) {
          console.log("------------------------------------");
          console.log("Tie");
          console.log("------------------------------------");
        } else {
          console.log("------------------------------------");
          console.log("Computer won!!");
          console.log("------------------------------------");
          this.props.decrement();
        }
      });
  }

  render() {
    const { store } = this.context;
    console.log("------------------------------------");
    console.log(store);
    console.log("------------------------------------");
    return (
      <div className="AppTitle">
        <b>Score:</b>
        <div>
          <RoundedButton text="Rock" clickitem={this.clickitem} />
          <RoundedButton text="Paper" clickitem={this.clickitem} />
          <RoundedButton text="Scissors" clickitem={this.clickitem} />
        </div>
      </div>
    );
  }
}

function mapStateToProp(state) {
  return { score: state };
}

export default connect(mapStateToProp, actions)(App);

我收到错误

Unhandled Rejection (TypeError): Cannot read property 'props' of undefined
(anonymous function)
http://localhost:3000/static/js/bundle.js:18380:15
  18377 |       console.log("------------------------------------");
  18378 |       console.log("Computer won!!");
  18379 |       console.log("------------------------------------");
> 18380 |       this.props.decrement();
        |           ^  18381 |     }
  18382 |   });
  18383 | }
View source

任何人都可以暗示我的错误吗?

3 个答案:

答案 0 :(得分:3)

如果可能,请将您的动作创建者功能更改为: -

export const INCREMENT = "SCORE_INCREMENT";
export const DECREMENT = "SCORE_DECREMENT";


  export function increment() {
    return {
      type: INCREMENT
    };
  }

  export function decrement() {
    return {
      type: DECREMENT
    };
  }

让我知道这是否有效。

同样在你的clickItem函数里面把它作为第一行: -

var that = this;

然后使用

访问增量和减量
that.props.decrement()

答案 1 :(得分:2)

看起来像上下文问题。尝试在fetch中使用箭头函数。

  fetch(url)
      .then((response) => {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then((data) => {
        var computer = data.item;
        console.log("------------------------------------");
        console.log(user + computer);
        console.log("------------------------------------");
        if (
          (user === "Rock" && computer === "Scissors") ||
          (user === "Paper" && computer === "Rock") ||
          (user === "Scissors" && computer === "Paper")
        ) {
          console.log("------------------------------------");
          console.log("User won!!");
          console.log("------------------------------------");
          this.props.increment();
        } else if (user === computer) {
          console.log("------------------------------------");
          console.log("Tie");
          console.log("------------------------------------");
        } else {
          console.log("------------------------------------");
          console.log("Computer won!!");
          console.log("------------------------------------");
          this.props.decrement();
        }
      });

答案 2 :(得分:1)

有一些问题,第一个问题是你没有绑定调用减量函数的函数。

其次,减量不能直接作为组件的支柱使用,而是在内部动作

第三,您需要发送您的行动。您可以将代码更改为以下

import scoreAction from "./actions/index";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      score: 0
    };
    this.clickitem = this.clickitem.bind(this);
  }

  clickitem (user)  {
    var url = "http://localhost:4000/generate-random";
    fetch(url)
      .then((response) => {
        if (response.status >= 400) {
          throw new Error("Bad response from server");
        }
        return response.json();
      })
      .then((data) => {
        var computer = data.item;
        console.log("------------------------------------");
        console.log(user + computer);
        console.log("------------------------------------");
        if (
          (user === "Rock" && computer === "Scissors") ||
          (user === "Paper" && computer === "Rock") ||
          (user === "Scissors" && computer === "Paper")
        ) {
          console.log("------------------------------------");
          console.log("User won!!");
          console.log("------------------------------------");
          this.props.increment();
        } else if (user === computer) {
          console.log("------------------------------------");
          console.log("Tie");
          console.log("------------------------------------");
        } else {
          console.log("------------------------------------");
          console.log("Computer won!!");
          console.log("------------------------------------");
          this.props.decrement();
        }
      });
  }

  render() {
    const { store } = this.context;
    console.log("------------------------------------");
    console.log(store);
    console.log("------------------------------------");
    return (
      <div className="AppTitle">
        <b>Score:</b>
        <div>
          <RoundedButton text="Rock" clickitem={this.clickitem} />
          <RoundedButton text="Paper" clickitem={this.clickitem} />
          <RoundedButton text="Scissors" clickitem={this.clickitem} />
        </div>
      </div>
    );
  }
}

function mapStateToProp(state) {
  return { score: state };
}
function mapDispatchToProps(dispatch) {
   return bindActionCreators({decrement: scoreAction.decrement, increment:  scoreAction.increment}, dispatch)
}
export default connect(mapStateToProp, mapDispatchToProps)(App);

同时将动作文件更改为

export const INCREMENT = "SCORE_INCREMENT";
export const DECREMENT = "SCORE_DECREMENT";

const scoreAction = {
  increment: function() {
    return {
      type: INCREMENT
    };
  },

  decrement: function() {
    return {
      type: DECREMENT
    };
  }
};

export default scoreAction;