javascript - react 如何修复子组件中的陈旧状态

标签 javascript reactjs react-hooks

创建多个子组件,每个子组件都可以设置其父组件的状态,使这些子组件具有不同版本的状态历史(也称为陈旧状态)

重现错误:

  1. 点击“添加新社交媒体”创建 2 个子组件
  2. 提交两个子组件以设置父状态
  3. 再次提交第一个创建的组件,现在第二个组件输入从结果状态中消失

另一个错误:

  1. 点击“添加新社交媒体”创建 2 个子组件
  2. 提交二次创建的子组件
  3. 提交第一个创建的子组件,现在第二个组件输入从结果状态中消失

总而言之,我希望结果状态包含每个组件的所有数据。我该如何解决这个问题?

https://codesandbox.io/s/blissful-fog-oz10p

const Admin = () => {
  const [links, setLinks] = useState({});
  const [newLink, setNewLink] = useState([]);

  const updateLinks = (socialMedia, url) => {
    setLinks({
      ...links,
      [socialMedia]: url
    });
  };

  const linkData = {
    links,
    updateLinks
  };

  const applyChanges = () => {
    console.log(links);
  };

  return (
    <>
      {newLink ? newLink.map(child => child) : null}
      <div className="container-sm">
        <Button
          type="submit"
          fullWidth
          variant="contained"
          color="primary"
          onClick={() => {
            setNewLink([
              ...newLink,
              <AddNewLink key={Math.random()} linkData={linkData} />
            ]);
          }}
        >
          Add new social media
        </Button>
        <Button
          type="submit"
          fullWidth
          variant="contained"
          color="primary"
          style={{ marginTop: "50px" }}
          onClick={() => applyChanges()}
        >
          Apply Changes
        </Button>
        <h3>{JSON.stringify(links, null, 4)}</h3>
      </div>
    </>
  );
};

export default Admin;

const AddNewLink = props => {
  const [socialMedia, setSocialMedia] = useState("");
  const [url, setUrl] = useState("");
  const { updateLinks } = props.linkData;

  const handleSubmit = () => {
    updateLinks(socialMedia, url);
  };

  return (
    <>
      <FormControl
        style={{ marginTop: "30px", marginLeft: "35px", width: "90%" }}
      >
        <InputLabel>Select Social Media</InputLabel>
        <Select
          value={socialMedia}
          onChange={e => {
            setSocialMedia(e.target.value);
          }}
        >
          <MenuItem value={"facebook"}>Facebook</MenuItem>
          <MenuItem value={"instagram"}>Instagram</MenuItem>
          <MenuItem value={"tiktok"}>TikTok</MenuItem>
        </Select>
      </FormControl>
      <form
        noValidate
        autoComplete="off"
        style={{ marginBottom: "30px", marginLeft: "35px" }}
      >
        <TextField
          id="standard-basic"
          label="Enter link"
          style={{ width: "95%" }}
          onChange={e => {
            setUrl(e.target.value);
          }}
        />
      </form>
      <div className="container-sm">
        <Button
          type="submit"
          fullWidth
          variant="contained"
          color="primary"
          style={{ marginBottom: "30px" }}
          onClick={() => handleSubmit()}
        >
          Submit
        </Button>
      </div>
    </>
  );
};

export default AddNewLink;

最佳答案

您遇到的问题是由 updateLinks() 函数 关闭 links 状态引起的。

当您创建两个 AddNewLink 组件时,它们中的每一个都被传递给 updateLinks() 函数。因为最初,links 是一个空对象,updateLinks() 函数传递给 AddNewLink 的两个实例,在 links 上有一个闭包 变量和 links 当时指的是一个空对象 {}。所以当你提交表单时,就updateLinks()函数而言,links是一个空对象。因此,当 links 与从 AddNewLink 组件传递的数据合并时,只有来自提交表单的数据被保存在状态中,因为 links 是一个空的对象。

解决方案:

您可以使用 useRef Hook 在 updateLinks() 函数中访问 links 的最新值。

const Admin = () => {
   ...
   
   const linkRef = useRef();

   const updateLinks = (socialMedia, url) => {
      linkRef.current = { ...linkRef.current, [socialMedia]: url };
      setLinks(linkRef.current);
   };
   
   ...
};

此外,我认为您不需要多个 AddNewLink 组件实例。您可以仅使用一个 AddNewLink 组件实例在状态中添加多个社交媒体链接。

演示:

Edit sharp-tdd-hym00

关于javascript - react 如何修复子组件中的陈旧状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63086881/

相关文章:

html - 我该怎么做才能单击 html 复选框并更改 html 输入的内容?

reactjs - Typescript 编译器不强制执行泛型

javascript - reactJS props 和 refs 有什么区别?

reactjs - 是否可以创建 React Hook 工厂函数?

javascript回调函数,变量映射

JavaScript:严格模式和匿名函数

Javascript:获取当前元素的同级元素 [CKEditor 需要]

javascript - react : setState from imported image?

javascript - 如何将当前i的for循环值添加到 react 功能组件中的空数组状态中?

javascript - useEffect,覆盖if语句