为什么我无法从定义它的组件内部访问更新的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];
};
这一切都与上下文有关。 如果你把console.log(receipes)
放在useEffect和渲染函数本身中,你可以看到事件流是什么:
- 第一个渲染配方为空。
- UseEffect被调用并将setBookmark放在配方中(但setBookmark的配方为空(
- 调用第二个渲染,现在配方具有"testesttest",
recipe.setBookmark
是一个函数,其中绑定到它的配方对象是事件 1 中的配方值 - setBookmark 被调用,recipe 现在设置为 "onetwothree",但 recipe 对象为空,因此我们将 setBookmark 设置为 undefined。
而不是将函数保留在状态中,您只需直接调用它(即返回 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];
};