0

为什么我无法从定义它的组件内部访问更新的recipes( ) 值?useState

在此示例中,您可以看到一旦删除对我用来更新状态的函数的引用,无法访问此值会导致应用程序出错

=> 代码框和代码如下

*点击两次<h1>查看错误

https://codesandbox.io/s/sparkling-sea-5iqgo?fontsize=14&hidenavigation=1&theme=dark

import React, { useEffect, useState } from "react";

export default function App() {
  const [userRecipes, setUserRecipes] = useRecipesData();

  return (
    <div className="App">
      <h1
        onClick={() => {
          userRecipes.setBookmarks("onetwothree");
        }}
      >
        Hello CodeSandbox
      </h1>
      <h2>{userRecipes.bookmarked_recipes}</h2>
    </div>
  );
}

const useRecipesData = () => {
  const [recipes, setRecipes] = useState({});

  const setBookmarks = newRecipes => {
    console.log(recipes); // is undefined !? and deletes setBookmarks
    setRecipes({
      bookmarked_recipes: newRecipes,
      setBookmarks: recipes.setBookmarks
    });
  };

  useEffect(() => {
    setRecipes({
      bookmarked_recipes: "testtesttest",
      setBookmarks: setBookmarks
    });
  }, []);

  return [recipes, setRecipes];
};

我不明白为什么如果我返回[recipes, setRecipes]存储recipes.setBookmarks对函数的引用的位置,它就不起作用

但是如果我返回函数本身(这也是一个参考),[recipes, setBookmarks]那么它就可以工作

查看其他可以正常工作的代码框

https://codesandbox.io/s/red-violet-gju99?fontsize=14&hidenavigation=1&theme=dark

import React, { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [userRecipes, setUserRecipes] = useRecipesData();

  return (
    <div className="App">
      <h1
        onClick={() => {
          setUserRecipes("onetwothree" + Math.random());
        }}
      >
        Hello CodeSandbox
      </h1>
      <h2>{userRecipes.bookmarked_recipes}</h2>
    </div>
  );
}

const useRecipesData = () => {
  const [recipes, setRecipes] = useState({});

  const setBookmarks = newRecipes => {
    console.log(recipes); // is defined this time
    setRecipes({
      bookmarked_recipes: newRecipes,
      setBookmarks: recipes.setBookmarks
    });
  };

  useEffect(() => {
    setRecipes({
      bookmarked_recipes: "testtesttest",
      setBookmarks: setBookmarks
    });
  }, []);

  return [recipes, setBookmarks];
};
4

1 回答 1

1

这都是关于上下文的。如果您将console.log(receipes)useEffect 和 render 函数本身放入,您可以看到事件流是什么:

  1. 第一个渲染配方是空的。
  2. 调用 UseEffect 并将 setBookmark 放入配方中(但 setBookmark 的配方为空)
  3. 调用第二个渲染,现在配方具有“testesttest”并且recipe.setBookmark是一个函数,其中绑定到它的配方对象是来自事件 1 的配方值
  4. setBookmark 被调用,recipe 现在设置为“onetwothree”,但是 recipe 对象是空的,所以我们将 setBookmark 设置为 undefined。

而不是将函数保持在状态中,您只需直接调用它(IE 返回 setBookmark 而不是 setRecipes,如下所示:

import React, { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [userRecipes, setBookmarks] = useRecipesData();

  return (
    <div className="App">
      <h1
        onClick={() => {
          setBookmarks("onetwothree" + Math.random());
        }}
      >
        Hello CodeSandbox
      </h1>
      <h2>{userRecipes.bookmarked_recipes}</h2>
    </div>
  );
}

const useRecipesData = () => {
  const [recipes, setRecipes] = useState({});
  const setBookmarks = newRecipes => {
    setRecipes({
      bookmarked_recipes: newRecipes,
    });
  };

  useEffect(() => {
    setRecipes({
      bookmarked_recipes: "testtesttest",
    });
  }, []);

  return [recipes, setBookmarks];
};
于 2020-01-15T18:36:29.800 回答