簡體   English   中英

反應如何修復子組件中過時的 state

[英]React how to fix stale state in child component

創建多個子組件,每個子組件都可以設置其父組件的狀態,使這些子組件具有不同版本的 state 歷史(又名陳舊狀態)

要重現錯誤:

  1. 通過單擊“添加新社交媒體”創建 2 個子組件
  2. 提交兩個子組件以設置父 state
  3. 再次提交第一個創建的組件,現在第二個組件輸入從生成的 state 中消失

另一個錯誤:

  1. 通過單擊“添加新社交媒體”創建 2 個子組件
  2. 提交第二個創建的子組件
  3. 提交第一個創建的子組件,現在第二個組件輸入從生成的 state 中消失

總而言之,我希望生成的 state 擁有每個組件的所有數據。 我怎樣才能解決這個問題?

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() function關閉links state 引起的。

當您創建兩個AddNewLink組件時,每個組件都會傳遞updateLinks() function。 由於最初, links是一個空的 object, updateLinks() function 傳遞給AddNewLink的兩個實例,對links變量有一個閉包,當時的links是指一個空的 ZA8CFDE6331BD59EB2AC96F8911C4B6 {} 6。 因此,當您提交表單時,就updateLinks() function 而言, links是一個空的 object。 因此,當將links與從AddNewLink組件傳遞的數據合並時,只有來自提交表單的數據會保存在 state 中,因為links是一個空的 object。

解決方案:

您可以使用useRef掛鈎訪問updateLinks() function 中links的最新值。

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

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

此外,我認為您不需要多個AddNewLink組件實例。 您可以在 state 中添加多個社交媒體鏈接,只需一個AddNewLink組件實例。

演示:

編輯 sharp-tdd-hym00

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM