反应useContext不触发重新渲染

时间:2020-03-06 22:16:35

标签: javascript reactjs

我在子组件AddMore.js中有一个按钮,该按钮可在列表中添加更多项,但它不会重新渲染呈现该列表Pig.js的其他子组件。我认为我的设置会起作用,因为我使用NextJS框架以类似的方式设置了上下文和提供程序。 Here's the source code, using codesandbox,或者您可以查看下面的代码。

App.js

import React, { useState } from "react";

import "./App.css";

import PigContext from "./store/PigContext";

import Pig from "./Pig";
import AddMore from "./AddMore";

function App() {
  const [data, setData] = useState([
    { pig: "oink" },
    { pig: "bork" },
    { pig: "oinkoink" }
  ]);

  return (
    <div className="App">
      <header className="App-header">
        <PigContext.Provider value={{ data, setData }}>
          <Pig />
          <AddMore />
        </PigContext.Provider>
      </header>
    </div>
  );
}

export default App;

PigContext.js

import { createContext } from "react";

const PigContext = createContext(undefined);

export default PigContext;

Pig.js

import React, { useContext } from "react";

import PigContext from "./store/PigContext";

const Pig = () => {
  const { data } = useContext(PigContext);

  return (
    <div>
      {data.map(({ pig }, idx) => (
        <div key={idx}>{pig}</div>
      ))}
    </div>
  );
};

export default Pig;

AddMore.js

import React, { useContext } from "react";
import PigContext from "./store/PigContext";

export default function AddMore() {
  const { setData } = useContext(PigContext);

  return (
    <div>
      <button
        onClick={() =>
          setData(prev => {
            prev.push({ pig: "zoink" });
            console.log(prev);
            return prev;
          })
        }
      >
        add pig question
      </button>
    </div>
  );
}

2 个答案:

答案 0 :(得分:2)

您要通过调用push来更改状态对象,而应该返回一个新数组来更新组件。

AddMore.js:

...
  <button
    onClick={() =>
      setData(prev => (
        [...prev, ({ pig: "zoink" })]
      ))
    }
  >
...

答案 1 :(得分:0)

这是因为您在setData中使用push处于突变状态。使用不会改变状态的方法(例如concat)可以解决此问题。您的AddMore函数看起来像

function AddMore() {

 const { setData } = useContext(PigContext);

  return (
    <div>
      <button onClick={() => setData(prev => prev.concat({ pig: "zoink" }))}>
        add pig question
      </button>
    </div>
  );
}