英文:
react-redux Cannot read properties of undefined
问题
在这段代码中,我使用了 react-redux 和 react-router。react-redux 的版本比较旧,但我想知道在这段代码中(指的是 react-redux 和 react-router 的这个版本)我哪里出错了。我试图在 main.jsx 中获取 ingredients,然后在 OrderSummary 组件中使用它,但是我遇到了以下错误:
- 无法读取未定义的属性,
- 未找到状态。
main.jsx:
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import reducer from "./store/reducer";
export default function Main(props) {
const store = createStore(
reducer /* preloadedState, */,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
return (
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />} >
<Route index element={<App />} />
<Route
path="/burger-builder/order-page"
exact
element={
<OrderSummary
ingredients={props.ingredients}
totalPrice={props.totalPrice}
/>
}
/>
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
</BrowserRouter>
</Provider>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Main />);
BurgerBuilder.jsx:
import * as actionTypes from "../../store/action";
import { connect } from "react-redux";
function BurgerBuilder(props) {
return (
<>
<Burger ingredients={props.ings} />
<BurgerControls
addIngredients={props.onIngredientAdded}
removeIngredients={props.onIngredientRemoved}
totalprice={props.totalPrice}
disabled={disableButton}
/>
</>
);
}
const mapStateToProps = (state) => {
return {
ings: state.ingredients,
price: state.totalPrice,
};
};
const mapDispatchToProps = (dispatch) => {
return {
onIngredientAdded: (ingName) =>
dispatch({ type: actionTypes.ADD_INGREDIENT, ingredientName: ingName }),
onIngredientRemoved: (ingName) =>
dispatch({
type: actionTypes.REMOVE_INGREDIENT,
ingredientName: ingName,
}),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BurgerBuilder);
部分内容
reducer.js:
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.ADD_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredientName]: state.ingredients[action.ingredientName] + 1
},
totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
};
英文:
In this Code, I use react-redux and react-router. the react-redux version is old but I want to know where I went wrong in this piece of code (in this version of react-redux and react-router I meant).
I try to get ingredients in main.jsx and use it in OrderSummary Component but I got errors like:
- Cannot read properties of undefined,
- state not found.
main.jsx:
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import reducer from "./store/reducer";
export default function Main(props) {
const store = createStore(
reducer /* preloadedState, */,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
return (
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<App />} />
<Route
path="/burger-builder/order-page"
exact
element={
<OrderSummary
ingredients={props.ingredients}
totalPrice={props.totalPrice}
/>
}
/>
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
</BrowserRouter>
</Provider>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Main />);
BurgerBuilder.jsx:
import * as actionTypes from "../../store/action";
import { connect } from "react-redux";
function BurgerBuilder(props) {
return (
<>
<Burger ingredients={props.ings} />
<BurgerControls
addIngredients={props.onIngredientAdded}
removeIngredients={props.onIngredientRemoved}
totalprice={props.totalPrice}
disabled={disableButton}
/>
</>
);
}
const mapStateToProps = (state) => {
return {
ings: state.ingredients,
price: state.totalPrice,
};
};
const mapDispatchToProps = (dispatch) => {
return {
onIngredientAdded: (ingName) =>
dispatch({ type: actionTypes.ADD_INGREDIENT, ingredientName: ingName }),
onIngredientRemoved: (ingName) =>
dispatch({
type: actionTypes.REMOVE_INGREDIENT,
ingredientName: ingName,
}),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BurgerBuilder);
part of
reducer.js:
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.ADD_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredienName]: state.ingredients[action.ingredientName] + 1
},
totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
};
答案1
得分: 0
在你的 Main
组件中,你正在传递 props.ingredients
和 props.totalPrice
给 OrderSummary
,但是在 Main
中未定义 props
—— 当你使用 root.render(<Main />);
渲染 Main
时没有传递任何内容。
要解决这个问题,你可以像你在 BurgerBuilder
中做的那样,将 OrderStatus
连接到 Redux 存储:
function OrderSummary(props) {
// 访问映射的 props
const { ingredients, totalPrice } = props;
// ...
};
const mapStateToProps = (state) => {
return {
ingredients: state.ingredients,
totalPrice: state.totalPrice,
};
};
export default connect(mapStateToProps)(OrderSummary);
然后,在 Main
中,渲染 OrderSummary
时不需要使用 props
:
<Route path="/burger-builder/order-page" exact element={<OrderSummary />} />
此外,在你的 reducer 中有一个拼写错误。你在 ADD_INGREDIENT
情况下写成了 action.ingredienName
而不是 action.ingredientName
。以下是修复后的 reducer.js:
case actionTypes.ADD_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredientName]: state.ingredients[action.ingredientName] + 1
},
totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
};
英文:
In your Main
component, you're passing props.ingredients
and props.totalPrice
to OrderSummary
, but props
is not defined in Main
-- you don't pass any when you render Main
with root.render(<Main />);
.
To get around this, you can connect OrderStatus
to the Redux store like you do with BurgerBuilder
:
function OrderSummary(props) {
// access mapped props
const { ingredients, totalPrice } = props;
// ...
};
const mapStateToProps = (state) => {
return {
ingredients: state.ingredients,
totalPrice: state.totalPrice,
};
};
export default connect(mapStateToProps)(OrderSummary);
Then, in Main
, render OrderSummary
without props
:
<Route path="/burger-builder/order-page" exact element={<OrderSummary />} />
Also, there's a typo in your reducer. You wrote action.ingredienName
instead of action.ingredientName
in the ADD_INGREDIENT
case. Here's the fixed reducer.js:
case actionTypes.ADD_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredientName]: state.ingredients[action.ingredientName] + 1
},
totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论