UseContext не выполняет повторно компонент

Я опытный 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;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
29
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вы неправильно пишете контекст. Чтобы установить новое значение foodState, вы не можете использовать this.foodState, но вам нужно использовать хуки useState для сохранения и обновления значения.
  2. React.useEffect не использует глубокое сравнение объектов, поэтому условие в третьем компоненте никогда не срабатывает.

Это мое решение. Я не проверял это, но внес некоторые изменения, которые должны решить ваши проблемы и оптимизировать ваш код.

// 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;

Здравствуйте, большое спасибо за это. На самом деле вы действительно помогли и мотивировали меня продолжать этот проект. Еще раз большое спасибо. С уважением.

Nijaz 22.03.2022 06:51

Другие вопросы по теме