使用事件侦听器时,状态保持不变

时间:2019-06-01 09:23:58

标签: reactjs react-hooks

https://codesandbox.io/s/state-shenanigans-mifyg

这个代码示例有点不合常规,但是仍然让我感到困惑,所以我决定将其变成一个问题。

请打开上面的链接,然后播放示例。保持控制台保持打开状态。

当表单更改时,我正在调用console.log,并将其传递给状态。如您所见,更改问题时,它会记录正确的值(带有现有答案的新问题)。

但是,如果您随后更改答案,则会发现 old 问题已与新答案一起注销。

我想它与闭包有关,但我无法弄清楚。

import * as React from "react";
import { render } from "react-dom";

import "./styles.css";

function Faq({ onChange, data }) {
  const questionRef = React.createRef<HTMLInputElement>();
  const answerRef = React.createRef<HTMLInputElement>();

  React.useEffect(() => {
    if (questionRef.current) {
      questionRef.current.addEventListener("keydown", (e: any) => {
        onChange({ ...data, question: e.target.value });
      });
    }

    if (answerRef.current) {
      answerRef.current.addEventListener("keydown", (e: any) => {
        onChange({ ...data, answer: e.target.value });
      });
    }
  }, []);

  return (
    <div>
      <input ref={questionRef} type="text" defaultValue={data.question} />
      <input ref={answerRef} type="text" defaultValue={data.answer} />
    </div>
  );
}

const App = () => {
  const [faq, setFaq] = React.useState({
    id: "1",
    question: "I am a question?",
    answer: "I am the answer!"
  });
  React.useEffect(() => {
    console.log(faq);
  }, [faq]);
  return <Faq data={faq} onChange={setFaq} />;
};

const rootElement = document.getElementById("root");
render(<App />, rootElement);

2 个答案:

答案 0 :(得分:0)

我不确定您所说的“旧”和“新”问题是什么意思,因为只有一个问题。无论如何,您都不必在React中使用DOM引用和手动的EvenListeners。 React是为您处理这类事情而发明的!

function Faq({ onChange, data }) {

  const handleChange = (e) => {
    console.log("the new value is")
    console.log(e.currentTarget.value)
  }

  return (
    <div>
      <input onChange={handleChange} type="text" defaultValue={data.question} />
      <input onChange={handleChange} type="text" defaultValue={data.answer} />
    </div>
  );
}

答案 1 :(得分:0)

您将需要刷新数据:

import * as React from "react";
import { render } from "react-dom";

import "./styles.css";

function Faq({ onChange, data }) {
  const questionRef = React.createRef<HTMLInputElement>();
  const answerRef = React.createRef<HTMLInputElement>();

  React.useEffect(() => {
    if (questionRef.current) {
      questionRef.current.addEventListener("keydown", (e: any) => {
        onChange({ ...data, question: e.target.value });
        data.question = e.target.value;
      });
    }

    if (answerRef.current) {
      answerRef.current.addEventListener("keydown", (e: any) => {
        onChange({ ...data, answer: e.target.value });
        data.answer = e.target.value;
      });
    }
  }, []);

  return (
    <div>
      <input ref={questionRef} type="text" defaultValue={data.question} />
      <input ref={answerRef} type="text" defaultValue={data.answer} />
    </div>
  );
}

const App = () => {
  const [faq, setFaq] = React.useState({
    id: "1",
    question: "I am a question?",
    answer: "I am the answer!"
  });
  React.useEffect(() => {
    console.log(faq);
  }, [faq]);
  return <Faq data={faq} onChange={setFaq} />;
};

const rootElement = document.getElementById("root");
render(<App />, rootElement);

https://codesandbox.io/s/state-shenanigans-kupjj