React Hooks - useState 使用在 useEffect 期间设置的另一个钩子变量的结果

时间:2021-04-05 16:05:45

标签: reactjs react-hooks

问题:我正在使用 useEffect 将数据从 API 加载到我的功能应用程序组件中(以下示例)。我无法理解如何设置变量 activeToken,因为 phrases 尚未定义,也许是因为 useEffect 是异步的?

在调用 phrases 之前,我应该使用什么模式来确保 activeToken 存在?

function App() {

  const getActiveToken = (tokens) => {
    for(let i = 0; i < tokens.length; i++) {
      if (tokens[i].mask === true) {
        return i
      }
    }
  }

  useEffect(() => {
    fetch('http://localhost:5000/api/v1')
      .then((response) => response.json())
      .then((data) => setPhrases(data))
  }
  )


  const [termIndex, setTermIndex] = useState(0);
  const [phrases, setPhrases] = useState([]);
  const [activeToken, setActiveToken] = useState(getActiveToken(phrases[termIndex].tokens))}

3 个答案:

答案 0 :(得分:1)

您正在尝试将 activeToken 的初始状态设置为将异步更新的状态 (phases)。由于组件挂载时 phases 未就绪,因此在 phases 更改时不会更新,因为初始值仅在第一次渲染(useState 初始化)时使用。

由于activeToken派生自tokens,而phases派生自useMemo,因此可以在组件体中进行计算,并用tokens包裹起来,所以它只会在 tokens 改变时计算,但不是绝对必要的,除非 phrases[termIndex].tokens 很大。此外,表达式 phrases[termIndex] 会抛出错误,因为 undefinedconst getActiveToken = (tokens = []) => { for(let i = 0; i < tokens.length; i++) { if (tokens[i].mask === true) { return i } } } function App() { useEffect(() => { fetch('http://localhost:5000/api/v1') .then((response) => response.json()) .then((data) => setPhrases(data)) }); const [termIndex, setTermIndex] = useState(0); const [phrases, setPhrases] = useState([]); const tokens = phrases[termIndex]?.tokens; const activeToken = useMemo(() => getActiveToken(tokens), [tokens]);

Code
=====
Fav_Food=[]
for Food in range(2):
  Fav_Food.append({
  "name":'',
  "Food":[]
  })
  Fav_Food[Food]["name"]=str(input("Enter Your name"))
  for food1 in range(5):
    user1=str(input("Enter your fav item" + str(food1+1)))
    Fav_Food[Food]["Food"].append(user1)
for items in range(len(Fav_Food)):
  print(Fav_Food[items]["name"] +" Your Favourite Food items are")
  print (Fav_Food[items]["Food"] )



Output
=======

Enter Your nameGaurav
Enter your fav item1a
Enter your fav item2b
Enter your fav item3c
Enter your fav item4d
Enter your fav item5e
Enter Your nameGarvit
Enter your fav item1g
Enter your fav item2h
Enter your fav item3j
Enter your fav item4k
Enter your fav item5l
Gaurav Your Favourite Food items are
['a', 'b', 'c', 'd', 'e']
Garvit Your Favourite Food items are
['g', 'h', 'j', 'k', 'l']

答案 1 :(得分:0)

制作一个包含异步代码的单独 async 函数并在 useEffect 中调用它。

//seperate function
const fetcher = async () => {
    fetch('http://localhost:5000/api/v1')
      .then((response) => response.json())
      .then((data) => setPhrases(data))
}

useEffect(() => {
   fetcher();
}

你也可以

useEffect(() => {
    //within useEffect
    let fetcher = async () => {
        fetch('http://localhost:5000/api/v1')
          .then((response) => response.json())
          .then((data) => setPhrases(data))
    }

    fetcher();
}

答案 2 :(得分:0)

试试这个方向: 请尝试以下操作:

function App() {

  const [activeToken, setActiveToken] = useState() // activeToken can't be set in the initial run anyway

  useEffect(() => {
    fetch('http://localhost:5000/api/v1')
      .then((response) => response.json())
      .then((tokens) => {
        for(let i = 0; i < tokens.length; i++) {
        if (tokens[i].mask === true) {
          setActiveToken(tokens[i])
        }
      }



  })

}