Redux and React. Uncaught TypeError: Cannot read property 'dispatch' of undefined
Redux and React. Uncaught TypeError: Cannot read property 'dispatch' of undefined
我正在尝试从深层嵌套的组件调用分派。
我正在使用 Redux 和 React。
我的应用结构是:
[应用]
----[主要]
--------[咖啡店]
--------[其他组件]
当我从 app.jsx 调用 'dispatch' 时,它起作用了。
当我从 Main 组件调用 'dispatch' 时它工作,当我从 render() 方法调用 dispatch 时(它有警告,但仍然有效),但当我调用 [=58= 时不起作用] 来自其他地方。
我使用 Provider 和 addNewItemToCart() 作为道具传递商店,但是当我从 ShopCoffee 组件调用 addNewItemToCart 时,出现错误:
"Uncaught TypeError: Cannot read property 'dispatch' of undefined"
这是我的程序:
App.jsx
import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/main.component.jsx";
import { createStore } from "redux";
import { Provider } from "react-redux";
var app = document.getElementById("app");
function mainAppReducer(state, action) {
if (!state) return {
text: 'test text 1231'
}
switch (action.type) {
case 'ADD_TO_CART' : console.log('ADD_TO_CART');
return Object.assign({}, state, { text : action.text });
}
}
const store = createStore(mainAppReducer);
store.dispatch ({
type : 'ADD_TO_CART',
text : 'One more message! ;)'
});
store.dispatch ({
type : 'ADD_TO_CART',
text : 'Text text message from redux! ;)'
});
console.log("store.getState() == ", store.getState());
var render = () => ReactDOM.render(<Provider store={store}><Main /></Provider>, app);
store.subscribe(render);
render();
console.log("store.getState() == ", store.getState());
main.component.jsx
import React from "react";
import Header from "./header.component.jsx";
import Footer from "./footer.component.jsx";
import Cart from "./cart.component.jsx";
import Checkout from "./checkout.component.jsx";
import ShopCoffee from "./shop-coffee.component.jsx";
import Rent from "./rent.component.jsx";
import Repair from "./repair.component.jsx";
import Contacts from "./contacts.component.jsx";
import { connect } from "react-redux";
export class Main extends React.Component {
constructor(props) {
super(props);
}
addNewItemToCart(itemsInCart) {
console.log("works");
console.log("addNewItemToCart() :: itemData == ", itemsInCart);
console.log("from Main: this.props", this.props);
this.props.dispatch({type : 'ADD_TO_CART'});
}
getItemsInCart(itemsInCart) {
console.log("getItemsInCart() :: itemData == ", itemsInCart);
return itemsInCart;
}
render() {
console.log('(from render) this.props == ', this.props);
console.log('dispatch==', this.props.dispatch);
return (
<main>
<Header />
<Cart getItemsInCart = {this.getItemsInCart} />
<Checkout />
<ShopCoffee addNewItemToCart = {this.addNewItemToCart}/>
<Rent />
<Repair />
<Contacts />
<Footer />
</main>
);
}
}
export default connect((store) => store)(Main);
店铺-coffee.component.jsx
import React from "react";
export default class ShopCoffee extends React.Component {
constructor(props) {
super(props);
console.log("ShopCoffee /constructor()");
console.log("ShopCoffee / this.props", this.props);
this.state = {shopItems : [], itemsInCart : []};
}
// =============== Добавляет выбранный товар в корзину ===============
addItemToCart(i) {
console.log("addItemToCart() i == ",i);
console.log("addItemToCart() :: this.props", this.props);
let newSelectedItem = this.state.shopItems[i];
this.state.itemsInCart.push(newSelectedItem);
this.props.addNewItemToCart(this.state.itemsInCart);
}
getData() {
const url="/data/coffee.json";
fetch(url)
.then((resp) => resp.json())
.then((data) => {
this.state.shopItems = data;
})
.catch((error) => console.error("Ошибка загрузки данных из файла", url));
}
componentWillMount() {
this.getData();
}
componentDidMount() {
setInterval(() => this.setState(this.state), 1000);
}
render() {
var itemsArr = [];
var itemsRow = [];
//console.log("this.state.shopItems ===", this.state.shopItems);
for (let i=0; i < this.state.shopItems.length; i++) {
let item = this.state.shopItems[i];
itemsArr.push(
<div className="shop-coffee__item" key={"item"+i}>
<div className="shop-coffee__item__inner">
<div className="row">
<div className="shop-coffee__item__kg">
<p className="shop-coffee__item__kg__text">{item.weight}</p>
</div>
<div className="shop-coffee__item__space">
</div>
<div className="shop-coffee__item__price">
<p className="shop-coffee__item__price__text">{item.price}</p>
</div>
</div>
<div className="row">
<div className="shop-coffee__item__image">
<img className="shop-coffee__item__image__img" src="img/template-img__coffee-shop.jpg" />
</div>
</div>
<div className="row">
<div className="shop-coffee__item__description">
<p className="shop-coffee__item__description__text">
{item.title}
</p>
<p className="shop-coffee__item__description__text">
{item.description}
</p>
</div>
</div>
<div className="row">
<div className="shop-coffee__item__button-container">
<button className="shop-coffee__item__button-container__button" onClick={this.addItemToCart.bind(this, i)}>
Заказать
</button>
</div>
</div>
</div>
</div>
);
if ( ((i>0) && (i%3 == 0)) || (i == this.state.shopItems.length-1)) {
itemsRow.push(
<div className="row" key={"row"+i}>
{itemsArr}
</div>);
itemsArr = [];
}
}
return (
<section className="shop-coffee">
<div className="container">
<div className="row">
<div className="shop-coffee__title-container">
<h2 className="shop-coffee__title-container__title">
Магазин кофе
</h2>
</div>
</div>
{itemsRow}
</div>
</section>
);
}
}
我认为您在组件的构造函数中缺少绑定到 class 实例的回调:
constructor(props) {
super(props);
...
this.addNewItemToCart = this.addNewItemToCart.bind(this);
}
基本上:如果你使用ES6 class,你需要绑定回调函数
有关详细信息,请参阅 React 文档:
我正在尝试从深层嵌套的组件调用分派。 我正在使用 Redux 和 React。
我的应用结构是:
[应用]
----[主要]
--------[咖啡店]
--------[其他组件]
当我从 app.jsx 调用 'dispatch' 时,它起作用了。
当我从 Main 组件调用 'dispatch' 时它工作,当我从 render() 方法调用 dispatch 时(它有警告,但仍然有效),但当我调用 [=58= 时不起作用] 来自其他地方。
我使用 Provider 和 addNewItemToCart() 作为道具传递商店,但是当我从 ShopCoffee 组件调用 addNewItemToCart 时,出现错误: "Uncaught TypeError: Cannot read property 'dispatch' of undefined"
这是我的程序:
App.jsx
import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/main.component.jsx";
import { createStore } from "redux";
import { Provider } from "react-redux";
var app = document.getElementById("app");
function mainAppReducer(state, action) {
if (!state) return {
text: 'test text 1231'
}
switch (action.type) {
case 'ADD_TO_CART' : console.log('ADD_TO_CART');
return Object.assign({}, state, { text : action.text });
}
}
const store = createStore(mainAppReducer);
store.dispatch ({
type : 'ADD_TO_CART',
text : 'One more message! ;)'
});
store.dispatch ({
type : 'ADD_TO_CART',
text : 'Text text message from redux! ;)'
});
console.log("store.getState() == ", store.getState());
var render = () => ReactDOM.render(<Provider store={store}><Main /></Provider>, app);
store.subscribe(render);
render();
console.log("store.getState() == ", store.getState());
main.component.jsx
import React from "react";
import Header from "./header.component.jsx";
import Footer from "./footer.component.jsx";
import Cart from "./cart.component.jsx";
import Checkout from "./checkout.component.jsx";
import ShopCoffee from "./shop-coffee.component.jsx";
import Rent from "./rent.component.jsx";
import Repair from "./repair.component.jsx";
import Contacts from "./contacts.component.jsx";
import { connect } from "react-redux";
export class Main extends React.Component {
constructor(props) {
super(props);
}
addNewItemToCart(itemsInCart) {
console.log("works");
console.log("addNewItemToCart() :: itemData == ", itemsInCart);
console.log("from Main: this.props", this.props);
this.props.dispatch({type : 'ADD_TO_CART'});
}
getItemsInCart(itemsInCart) {
console.log("getItemsInCart() :: itemData == ", itemsInCart);
return itemsInCart;
}
render() {
console.log('(from render) this.props == ', this.props);
console.log('dispatch==', this.props.dispatch);
return (
<main>
<Header />
<Cart getItemsInCart = {this.getItemsInCart} />
<Checkout />
<ShopCoffee addNewItemToCart = {this.addNewItemToCart}/>
<Rent />
<Repair />
<Contacts />
<Footer />
</main>
);
}
}
export default connect((store) => store)(Main);
店铺-coffee.component.jsx
import React from "react";
export default class ShopCoffee extends React.Component {
constructor(props) {
super(props);
console.log("ShopCoffee /constructor()");
console.log("ShopCoffee / this.props", this.props);
this.state = {shopItems : [], itemsInCart : []};
}
// =============== Добавляет выбранный товар в корзину ===============
addItemToCart(i) {
console.log("addItemToCart() i == ",i);
console.log("addItemToCart() :: this.props", this.props);
let newSelectedItem = this.state.shopItems[i];
this.state.itemsInCart.push(newSelectedItem);
this.props.addNewItemToCart(this.state.itemsInCart);
}
getData() {
const url="/data/coffee.json";
fetch(url)
.then((resp) => resp.json())
.then((data) => {
this.state.shopItems = data;
})
.catch((error) => console.error("Ошибка загрузки данных из файла", url));
}
componentWillMount() {
this.getData();
}
componentDidMount() {
setInterval(() => this.setState(this.state), 1000);
}
render() {
var itemsArr = [];
var itemsRow = [];
//console.log("this.state.shopItems ===", this.state.shopItems);
for (let i=0; i < this.state.shopItems.length; i++) {
let item = this.state.shopItems[i];
itemsArr.push(
<div className="shop-coffee__item" key={"item"+i}>
<div className="shop-coffee__item__inner">
<div className="row">
<div className="shop-coffee__item__kg">
<p className="shop-coffee__item__kg__text">{item.weight}</p>
</div>
<div className="shop-coffee__item__space">
</div>
<div className="shop-coffee__item__price">
<p className="shop-coffee__item__price__text">{item.price}</p>
</div>
</div>
<div className="row">
<div className="shop-coffee__item__image">
<img className="shop-coffee__item__image__img" src="img/template-img__coffee-shop.jpg" />
</div>
</div>
<div className="row">
<div className="shop-coffee__item__description">
<p className="shop-coffee__item__description__text">
{item.title}
</p>
<p className="shop-coffee__item__description__text">
{item.description}
</p>
</div>
</div>
<div className="row">
<div className="shop-coffee__item__button-container">
<button className="shop-coffee__item__button-container__button" onClick={this.addItemToCart.bind(this, i)}>
Заказать
</button>
</div>
</div>
</div>
</div>
);
if ( ((i>0) && (i%3 == 0)) || (i == this.state.shopItems.length-1)) {
itemsRow.push(
<div className="row" key={"row"+i}>
{itemsArr}
</div>);
itemsArr = [];
}
}
return (
<section className="shop-coffee">
<div className="container">
<div className="row">
<div className="shop-coffee__title-container">
<h2 className="shop-coffee__title-container__title">
Магазин кофе
</h2>
</div>
</div>
{itemsRow}
</div>
</section>
);
}
}
我认为您在组件的构造函数中缺少绑定到 class 实例的回调:
constructor(props) {
super(props);
...
this.addNewItemToCart = this.addNewItemToCart.bind(this);
}
基本上:如果你使用ES6 class,你需要绑定回调函数 有关详细信息,请参阅 React 文档: