我尝试将操作“ addProduct”添加到组件中。但是当我单击它时看到一个错误,请帮助我,谢谢!
我不知道我的错误在哪里(
import { bindActionCreators } from "redux";
import { addProduct } from "../actions/addProduct";
const ProductListItem = ({ product }) => {
return (
<div className="product">
<img className="product_img" src={product.image} />
<p>{product.name}</p>
<p className="bold">$ {product.price}</p>
<button className="add_card" onClick={() => addProduct(product)}>
{" "}
add to cart
</button>
</div>
);
};
export default ({ products = [] }) =>
products.map((product, i) => {
return <ProductListItem key={i} product={product} />;
});
const mapDispatchToProps = dispatch => {
return bindActionCreators({ addProduct }, dispatch);
};
connect(null,
mapDispatchToProps
)(ProductListItem);
[enter image description here][1]
答案 0 :(得分:1)
我做了一些更新,并举例说明了我在做什么。
connect
导入react-redux
addProduct
,
您已使用mapDispatchToProps
mapDispatchToProps
重新定义为不使用bindActionCreators
,
这只是一个偏好问题,但是任何一个都可以。connect()
中,我使用...rest
破坏所有剩余的道具
并将其作为道具散布到返回中。..
import React from "react"
import ProductListItem from "./ProductListItem"
const products = [1,2,3] <-- data might be in redux-state but I'll use this for simplicity.
const TestHolder = () => {
return(
<div>
<ProductListItem products={products}/>
</div>
)
}
export default TestHolder
import React from "react"
import { connect } from "react-redux"
import { addProduct } from "../../actions/testActions";
const ProductListItem = ({ product, addProduct }) => {
return (
<div className="product">
<button className="add_card" onClick={() => addProduct()}>
{" "}
add to cart
</button>
</div>
);
};
const mapDispatchToProps = dispatch => {
return {
addProduct: (product) => {
dispatch(addProduct(product))
}
}
};
export default connect(null, mapDispatchToProps)(({ products = [], ...rest }) =>
products.map((product, i) => {
return <ProductListItem key={i} product={product} {...rest} />;
}))
export const addProduct = () => {
return {
type: "Woof"
}
}
您可能将动作创建者的格式设置为畸形,并使其成为普通对象,而不是将其返回给对象的函数。
答案 1 :(得分:0)
要正确添加操作,您需要使用redux connect函数将调度映射到您的组件。
function connect(mapStateToProps?, mapDispatchToProps?, ...)
第一个参数用于将状态映射到道具。
const mapStateToProps = state => {
return { products: state.products, cart: state.cart };
};
const Item = connect(mapStateToProps)(MyItemComp)
现在在组件中,您可以访问products
和cart
作为道具。您可以使用this.props.products
第二个参数用于允许您的组件分派操作。
function mapDispatchToProps(dispatch) {
return {
addProduct: e => dispatch(addProduct(e))
};
}
const Item = connect(mapStateToProps, mapDispatchToProps)(MyItemComp)
现在,我们可以通过执行addProduct(product)
从组件中分派动作。
connect可以像
一样使用// will only access props, won't dispatch any actions
const Item = connect(mapStateToProps)(MyItemComp)
// dispatch actions, won't access props
const Item = connect(null, mapDispatchToProps)(MyItemComp)
// will access props and dispatch actions
const Item = connect(mapStateToProps, mapDispatchToProps)(MyItemComp)
现在让我们修复您的组件
import { addProduct } from "../actions/addProduct";
import { connect } from "react-redux";
// add addProduct as a second parameter, to be able to dispatch actions from here
const ProductListItem = ({ product, addProduct }) => {
return (
<div className="product">
<img className="product_img" src={product.image} />
<p>{product.name}</p>
<p className="bold">$ {product.price}</p>
<button className="add_card" onClick={() => addProduct(product)}>
{" "}
add to cart
</button>
</div>
);
};
更改
export default ({ products = [] }) =>
products.map((product, i) => {
return <ProductListItem key={i} product={product} />;
});
到
// export ProductListItem
export default ({ products = [], addProduct }) =>
products.map((product, i) => {
return <ProductListItem key={i} product={product} addProduct={addProduct}/>;
});
现在我们需要附加道具和调度员
// import the above export
import ProductListItem from './ProductListItem';
const ProductList = connect(
mapStateToProps,
mapDispatchToProps
)(ProductListItem);
在您的父组件中
render() {
...
return(
<div>
...
<ProductList />
...
</div>
)
}
演示
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.0.3/react-redux.min.js"></script>
<script src="http://wzrd.in/standalone/uuid%2Fv1@latest"></script>
<link
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
crossorigin="anonymous"
/>
<style>
.product {
display: flex;
flex-direction: row;
border-bottom-style: solid;
margin-bottom: 5px;
margin-top: 10px;
}
img.product_img {
width: 30px;
}
.badge {
padding-left: 9px;
padding-right: 9px;
-webkit-border-radius: 9px;
-moz-border-radius: 9px;
border-radius: 9px;
}
.label-warning[href],
.badge-warning[href] {
background-color: #c67605;
}
#lblCartCount {
font-size: 12px;
background: #ff0000;
color: #fff;
padding: 0 5px;
vertical-align: top;
margin-left: 1px;
}
</style>
<div id="root"></div>
<script type="text/babel">
const { Provider, connect } = ReactRedux;
const { applyMiddleware, createStore, combineReducers } = Redux;
function addProduct(payload) {
return { type: 'ADD_PRODUCT', payload };
}
const initialState = {
products: [
{
id: 1,
name: 'Avocado',
price: 1.5,
image: 'https://img.icons8.com/metro/26/000000/avocado.png',
quantity: 0
},
{
id: 6,
name: 'Bread',
price: 1,
image: 'https://img.icons8.com/metro/26/000000/bread.png',
quantity: 0
},
{
id: 2,
name: 'Milk',
price: 1.8,
image: 'https://img.icons8.com/metro/26/000000/milk-bottle.png',
quantity: 0
}
],
cart: []
};
function rootReducer(state = initialState, action) {
if (action.type == 'ADD_PRODUCT') {
return {
...state,
cart: [...state.cart, action.payload]
};
}
return state;
}
const store = createStore(rootReducer);
const mapStateToProps = state => {
return { products: state.products, cart: state.cart };
};
function mapDispatchToProps(dispatch) {
return {
addProduct: e => dispatch(addProduct(e))
};
}
const CartItems = ({ cart }) => {
return (
<div>
<i class="fa fa-shopping-cart" />
<span class="badge badge-warning" id="lblCartCount">
{cart.length}
</span>
</div>
);
};
const ProductListItem = ({ product, addProduct }) => {
return (
<div className="product">
<img className="product_img" src={product.image} />
<p>{product.name}</p>
<p style={{ marginLeft: 5, marginRight: 5 }} className="bold">${product.price}</p>
<button className="add_card" onClick={() => addProduct(product)}>
{' '}
add to cart
</button>
</div>
);
};
const Cart = connect(mapStateToProps)(CartItems);
const Products = ({ products = [], addProduct }) =>
products.map((product, i) => {
return <ProductListItem key={i} product={product} addProduct={addProduct}/>;
});
const ProductList = connect(
mapStateToProps,
mapDispatchToProps
)(Products);
class App extends React.Component {
render() {
return (
<div>
<Cart />
<ProductList />
</div>
);
}
}
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
</script>