Использование контекстного API (React.js) для изменения только определенного ключа в объекте состояния

Я использую контекстный API для управления состоянием. Для этого я создал файл AppContext.js, в котором создал контекст и Provider:

import { useState, createContext } from "react";

export const AppContext = createContext();

export const AppProvider = (props) => {
   const [appdata, setAppdata] = useState({
      data1: "this is data1",
      data2: "this is data2",
   });

   return (
      <AppContext.Provider value={[appdata, setAppdata]}>
         {props.children}
      </AppContext.Provider>
   );
};

Я импортировал этого поставщика в родительский компонент приложения, то есть App.js. Также я завернул компонент <AppChild/> в Provider.

import AppChild from "./AppChild";
import { AppProvider } from "./AppContext";

const App = () => {
   return (
      <AppProvider>
         <div className="App">hello</div>
         <AppChild />
      </AppProvider>
   );
};

export default App;

Теперь из компонента AppChild мне нужно было только обновить ключ data1 моего состояния. Для этого я создал кнопку с onClick, с помощью которой я буду изменять свое состояние. Для этого я использовал следующий код в AppChild.js:

import { useContext } from "react";
import { AppContext } from "./AppContext";

const AppChild = () => {
   const [appdata, setAppdata] = useContext(AppContext);
   return (
      <div>
         <h3 style={{ color: "red" }}>Data for Appchild: {appdata.data1}</h3>
         <button
            onClick={() =>
               setAppdata((prev) => {
                  prev.data1 = "updated data1";
                  return prev;
               })
            }
         >
            click to change
         </button>
      </div>
   );
};

export default AppChild;

Но когда я нажимаю кнопку, текст внутри блока <h3> не меняется. Хотя, когда я изменяю все состояние, передавая весь объект непосредственно в setAppdata, как показано ниже, новый код

Таким образом, состояние обновляется успешно. Почему не работает первый метод, когда я только хотел изменить ключ data1?


person Tarun Khare    schedule 10.03.2021    source источник


Ответы (1)


Вы неправильно обновляете состояние, поэтому оно не работает. Вот как вы должны обновлять состояние

<button
 onClick={() =>
   setAppdata((prevState) => ({
     ...prevState,
     data1: "Your New Data"
        }))
      }
    >
        click to change
      </button>     
person Sayog    schedule 10.03.2021
comment
Ваше решение работает. Но можете ли вы сказать, что не так в моем методе, что мешает ему работать? Насколько я знаю, setAppdata () принимает неявную функцию. вы напрямую использовали () = ›(привет), а я использовал () =› {return hello}. Оба они технически одинаковы, если я не ошибаюсь. Пожалуйста, объясни... - person Tarun Khare; 10.03.2021
comment
Вы также обновляете состояние, но напрямую изменяете state, что не приведет к повторной визуализации. прочтите это для получения дополнительной информации. - person Sayog; 11.03.2021
comment
О, понял! Большое спасибо! - person Tarun Khare; 11.03.2021