Javascript 反应挂钩未设置为Useffect

Javascript 反应挂钩未设置为Useffect,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在使用useEffect从Trello获取一些数据并设置一些状态。首先,我抓起我要找的卡,打电话给setCard和setCardLocation。一切正常。然后我进入我的else案例,不管我做什么,setPublishDate将永远不会被设置,循环将继续运行。为什么其他的钩子都能用,而我的最后一个钩子不行?谢谢 export default function Home(props) { const [performedFetch, setPerformedFetch] = useStat

我正在使用useEffect从Trello获取一些数据并设置一些状态。首先,我抓起我要找的卡,打电话给setCard和setCardLocation。一切正常。然后我进入我的else案例,不管我做什么,setPublishDate将永远不会被设置,循环将继续运行。为什么其他的钩子都能用,而我的最后一个钩子不行?谢谢

export default function Home(props) {
  const [performedFetch, setPerformedFetch] = useState(false);
  const [slug, setSlug] = useState(null);
  const [cardLocation, setCardLocation] = useState(1);
  const [card, setCard] = useState(null);
  const [publishDate, setPublishDate] = useState(null);

  const key = ''; // imagine these are here
  const token = '';

  useEffect(() => {
    setSlug(
      new URLSearchParams(window.location.search).get('slug')
    );

    if (!performedFetch && !!slug) {
      fetch(`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`)
          .then(response => response.json())
          .then(data => {
            setPerformedFetch(true);

            data.forEach((c, index) => {
              if (c.desc.includes(slug)) {                    
                setCard(c)
                setCardLocation(index + 1)
              } else if (!publishDate && index > cardLocation) { 
                console.log(publishDate); // why is this always null?? also runs multiple times

                const name = c.name;
                const frontHalf = name.split("/")[0].split(" ");
                const month = frontHalf[frontHalf.length - 1];
                const day = name.split("/")[1].split(")")[0];
                setPublishDate(`${month}/${day}`);
              }
            });
        });
    }
  });
这是因为通常react状态是异步更新的,在检查slug时,它还没有设置

您需要这样做:

function Home(props) {
  const [performedFetch, setPerformedFetch] = useState(false);
  const [slug, setSlug] = useState(null);
  const [cardLocation, setCardLocation] = useState(1);
  const [card, setCard] = useState(null);
  const [publishDate, setPublishDate] = useState(null);

  const key = ""; // imagine these are here
  const token = "";

  useEffect(() => {
    setSlug(new URLSearchParams(window.location.search).get("slug"));
  });

  useEffect(() => {
    console.log(slug)
    if (!performedFetch && !!slug) {
      fetch(`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`)
          .then(response => response.json())
          .then(data => {
            setPerformedFetch(true);

            data.forEach((c, index) => {
              if (c.desc.includes(slug)) {                    
                setCard(c)
                setCardLocation(index + 1)
              } else if (!publishDate && index > cardLocation) { 
                console.log(publishDate); // why is this always null?? also runs multiple times

                const name = c.name;
                const frontHalf = name.split("/")[0].split(" ");
                const month = frontHalf[frontHalf.length - 1];
                const day = name.split("/")[1].split(")")[0];
                setPublishDate(`${month}/${day}`);
              }
            });
        });
    }
  }, [slug, performedFetch])
}
这是因为通常react状态是异步更新的,在检查slug时,它还没有设置

您需要这样做:

function Home(props) {
  const [performedFetch, setPerformedFetch] = useState(false);
  const [slug, setSlug] = useState(null);
  const [cardLocation, setCardLocation] = useState(1);
  const [card, setCard] = useState(null);
  const [publishDate, setPublishDate] = useState(null);

  const key = ""; // imagine these are here
  const token = "";

  useEffect(() => {
    setSlug(new URLSearchParams(window.location.search).get("slug"));
  });

  useEffect(() => {
    console.log(slug)
    if (!performedFetch && !!slug) {
      fetch(`https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`)
          .then(response => response.json())
          .then(data => {
            setPerformedFetch(true);

            data.forEach((c, index) => {
              if (c.desc.includes(slug)) {                    
                setCard(c)
                setCardLocation(index + 1)
              } else if (!publishDate && index > cardLocation) { 
                console.log(publishDate); // why is this always null?? also runs multiple times

                const name = c.name;
                const frontHalf = name.split("/")[0].split(" ");
                const month = frontHalf[frontHalf.length - 1];
                const day = name.split("/")[1].split(")")[0];
                setPublishDate(`${month}/${day}`);
              }
            });
        });
    }
  }, [slug, performedFetch])
}
正如前面提到的,您应该有两个useEffects

此外,通过提供依赖项数组作为useEffect的第二个参数来实现这一点也很重要。因此,只有当其任何依赖项发生变化时,效果才会重新运行

段塞的第一效果:

获取和设置卡和其他详细信息的第二个效果:

useEffect(() => {
  if (!performedFetch && slug) {
    fetch(
      `https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`
    )
      .then((response) => response.json())
      .then((data) => {
        setPerformedFetch(true)

      // Note: if there can be only ONE matching card
      const index = data.findIndex((card) => card.desc.includes(slug))
      if (index > -1) {
        const card = data[index]
        setCard(card)
        setCardLocation(index + 1)
        const name = card.name
        const frontHalf = name.split('/')[0].split(' ')
        const month = frontHalf[frontHalf.length - 1]
        const day = name.split('/')[1].split(')')[0]
        setPublishDate(`${month}/${day}`)
      }

      // Setting State in a LOOP? is a problem
      /*
      data.forEach((card, index) => {
        if (card.desc.includes(slug)) {
          setCard(card)
          setCardLocation(index + 1)
        } else if (!publishDate && index > cardLocation) {
          const name = card.name
          const frontHalf = name.split('/')[0].split(' ')
          const month = frontHalf[frontHalf.length - 1]
          const day = name.split('/')[1].split(')')[0]
          setPublishDate(`${month}/${day}`)
        }
      })*/

    })
  }
}, [slug, performedFetch])
:

因此,您不应该像当前那样在循环中设置状态。如果必须遍历循环并将数组的所有或少数元素设置为状态,则可以遍历数组并推送本地数组变量中的所有相关项,并在循环结束后将其设置为状态。希望有帮助

正如前面提到的,您应该有两个useEffects

此外,通过提供依赖项数组作为useEffect的第二个参数来实现这一点也很重要。因此,只有当其任何依赖项发生变化时,效果才会重新运行

slug的第一个效果:

获取和设置卡和其他详细信息的第二个效果:

useEffect(() => {
  if (!performedFetch && slug) {
    fetch(
      `https://api.trello.com/1/lists/${listId}/cards?key=${key}&token=${token}`
    )
      .then((response) => response.json())
      .then((data) => {
        setPerformedFetch(true)

      // Note: if there can be only ONE matching card
      const index = data.findIndex((card) => card.desc.includes(slug))
      if (index > -1) {
        const card = data[index]
        setCard(card)
        setCardLocation(index + 1)
        const name = card.name
        const frontHalf = name.split('/')[0].split(' ')
        const month = frontHalf[frontHalf.length - 1]
        const day = name.split('/')[1].split(')')[0]
        setPublishDate(`${month}/${day}`)
      }

      // Setting State in a LOOP? is a problem
      /*
      data.forEach((card, index) => {
        if (card.desc.includes(slug)) {
          setCard(card)
          setCardLocation(index + 1)
        } else if (!publishDate && index > cardLocation) {
          const name = card.name
          const frontHalf = name.split('/')[0].split(' ')
          const month = frontHalf[frontHalf.length - 1]
          const day = name.split('/')[1].split(')')[0]
          setPublishDate(`${month}/${day}`)
        }
      })*/

    })
  }
}, [slug, performedFetch])
:


因此,您不应该像当前那样在循环中设置状态。如果必须遍历循环并将数组的所有或少数元素设置为状态,则可以遍历数组并推送本地数组变量中的所有相关项,并在循环结束后将其设置为状态。希望有帮助

我认为这与此相关:@TaghiKhavari说的两个useEffect,或者只在useEffect-const slug=new-URLSearchParamswindow.location.search.get'slug'中本地使用slug。我认为这与此相关:@TaghiKhavari说的两个useEffect,或者在useffect-const slug=new URLSearchParamswindow.location.search.get'slug'中本地使用slug。很抱歉,这是不正确的。我的代码运行良好,slug从URL栏中被提取,因此slug与任何异步无关。我进入else块,它继续运行我获取的卡片。我希望它在我第一次调用SetDate后停止。设置后立即登录仍然返回null。@ZackShapiro,这是因为React将批处理所有setPublishDate调用,并在检查发布日期后更新状态,所以如何修复?谢谢你,但这是不对的。我的代码运行良好,slug是从URL栏中提取的,因此slug与异步无关。我进入else块,它继续运行我获取的卡片。我希望它在我第一次调用SetDate后停止。设置后立即登录仍然返回null。@ZackShapiro,这是因为React将批处理所有setPublishDate调用,并在检查发布日期后更新状态,所以如何修复?谢谢