Я опытный javascript-разработчик. Однако мне нужно двигаться дальше, поэтому сейчас я знаю несколько концепций. Я отлаживал этот код 4 часа и не нашел ни одной ошибки. Я имею в виду, что это, вероятно, связано с тем, что этот крючок немного сбивает с толку.
Какое приложение должно делать? По сути, он должен отображать пищевой компонент на основе фиктивных закодированных данных. Это работает хорошо. На этом вновь отображаемом компоненте должна быть форма с полем ввода. Когда мы отправляем форму, этот номер из формы должен быть взят и записан в пищевой объект. Объект должен выглядеть так: {Суши: 0}. Всякий раз, когда я отправляю, он должен обновляться. Кроме того, в объекте есть не одно свойство. Их может быть больше, например: {Суши: 0, Пицца: 0, Вишня: 0}. Это зависит от фиктивных данных. В начале приложения оно автоматически создает этот объект и переводит его в состояние. Затем я отправляю функцию обновления состояния дочернему компоненту, и когда мы отправляем форму, он обновляет состояние. Это прекрасно работает. Теперь для текущего компонента у меня есть useEffect. Это использование эффектов срабатывает всякий раз, когда изменяется состояние. Что он делает, так это обновляет контекст. Теперь, когда я обновляю контекст, в «третьем» компоненте должны быть взяты все значения и должна отображаться сумма значений. Проблема в том, что, что бы я ни пробовал, этот «третий» компонент не выполняется повторно...
Код: App.js
function App() {
return (
<FoodStateContext.Provider
value = {{
foodState: {},
setContext: function (val) {
this.foodState = val;
},
}}
>
<Header />
<BodyContainer>
<Card className = {styles["food-message"]}>
<h2>Delicious Food, Delivered To You</h2>
<p>
Choose your favourite meal from our broad selection of avaible meets
and enjoy a delicious lunch or dinner at home.
</p>
<p>
All our meals are cooked with high-quality ingredients, just-in-time
and of course by experienced chefs!
</p>
</Card>
<FoodContainer foodList = {food} />
</BodyContainer>
</FoodStateContext.Provider>
);
}
экспортировать приложение по умолчанию;
Пищевых контейнеров
import react, { useState, useEffect, useReducer, useContext } from "react";
import styles from "./FoodContainer.module.css";
import Card from "../UI/Card/Card";
import FoodComponent from "./FoodComponent";
import FoodStateContext from "../store/food-state-context";
const FoodContainer = (props) => {
const foodList = props.foodList;
const [foodState, setFoodState] = useState({});
const ctx = useContext(FoodStateContext);
useEffect(() => {
let obj = {};
for (let i = 0; i < foodList.length; i++) {
obj[foodList[i].name] = 0;
}
setFoodState(obj);
}, []);
console.info(foodState);
useEffect(() => {
console.info("muda");
ctx.foodState = foodState;
ctx.setContext(foodState);
console.info(ctx.foodState);
}, [foodState]);
return (
<Card className = {styles["food-container"]}>
{foodList.map((food) => {
return (
<FoodComponent
key = {food.name}
food = {food}
updateFoodState = {setFoodState}
></FoodComponent>
);
})}
</Card>
); };
экспортировать FoodContainer по умолчанию;
Пищевой компонент
import React, { useReducer, useEffect, useContext } from "react";
import styles from "./FoodComponent.module.css";
import Input from "../UI/Input/Input";
import Button from "../UI/Button/Button";
const FoodComponent = (props) => {
const food = props.food;
const formSubmitHandler = (e) => {
e.preventDefault();
props.updateFoodState((prevState) => {
return {
...prevState,
[food.name]: prevState[food.name] + +e.target[0].value,
};
});
};
return (
<div className = {styles["food-component"]}>
<div className = {styles["food-component__description"]}>
<p>{food.name}</p>
<p>{food.description}</p>
<p>{food.price}</p>
</div>
<form onSubmit = {formSubmitHandler}>
<div>
<div>
<span>Amount:</span>
<Input />
</div>
<Button type = "submit">+Add</Button>
</div>
</form>
</div>
);
};
export default FoodComponent;
Пищевой контекст
import react from "react";
const FoodStateContext = react.createContext({
foodState: "",
setContext: (val) => {
console.info(val);
this.foodState = val;
},
});
export default FoodStateContext;
Этот третий компонент
import React, { useState, useContext, useEffect } from "react";
import styles from "./Cart.module.css";
import FoodStateContext from "../store/food-state-context";
const Cart = (props) => {
const [totalProductsNumber, setTotalProductsNumber] = useState(0);
const ctx = useContext(FoodStateContext);
console.info(ctx.foodState);
useEffect(() => console.info("govna"), [ctx]);
return (
<div className = {styles.cart}>
<div>Ic</div>
<p>Your Cart</p>
<div>
<span>{totalProductsNumber}</span>
</div>
</div>
);
};
export default Cart;
Это мое решение. Я не проверял это, но внес некоторые изменения, которые должны решить ваши проблемы и оптимизировать ваш код.
// FoodStateProvider.js
import React from "react";
export const FoodStateContext = React.useContext({
foodState: {},
setFoodState: () => undefined,
});
// Use a custom provider to handle the context logic
export const FoodStateProvider = ({ children }) => {
const [foodState, setFoodState] = React.useState({});
return (
<FoodStateContext.Provider
value = {{
foodState,
setFoodState,
}}
>
{children}
</FoodStateContext.Provider>
);
};
Затем используйте FoodStateProvider в своем приложении.
// App.js
const App = () => (
<FoodStateProvider> ...your components </FoodStateProvider>
)
Затем я удалил useState в FoodContainer, потому что теперь вы обрабатываете его в контексте:
// FoodContainer.js
import React, { useState, useEffect, useContext } from "react";
import styles from "./FoodContainer.module.css";
import Card from "../UI/Card/Card";
import FoodComponent from "./FoodComponent";
import FoodStateContext from "../store/food-state-context";
const FoodContainer = ({ foodList }) => {
const ctx = useContext(FoodStateContext);
// The useEffect don't works well here, using a callback helps to remove
// additional data structures and conditions problems
const setFoodState = useCallback(({name, valueToAdd}) => {
// Logic from FoodComponent now is here
const newValue = (ctx.foodState[name] ?? 0) + valueToAdd;
ctx.setFoodState(currentFoodState => {...currentFoodState, [name]: newValue});
}, [foodState]);
return (
<Card className = {styles["food-container"]}>
{foodList.map((food) => (
<FoodComponent
key = {food.name}
food = {food}
updateFoodState = {setFoodState}
/>
))}
</Card>
);
};
// FoodComponent.js
import React, { useReducer, useEffect, useContext } from "react";
import styles from "./FoodComponent.module.css";
import Input from "../UI/Input/Input";
import Button from "../UI/Button/Button";
const FoodComponent = ({ food, updateFoodState }) => {
const formSubmitHandler = (e) => {
e.preventDefault();
updateFoodState({ name: food.name, valueToAdd: e.target[0].value });
};
return (
<div>
your components
<form onSubmit = {formSubmitHandler}> your form </form>
</div>
);
};
export default FoodComponent;
Здравствуйте, большое спасибо за это. На самом деле вы действительно помогли и мотивировали меня продолжать этот проект. Еще раз большое спасибо. С уважением.