将 useState 与 promise 一起使用是否只是一次设置值的好习惯?
Is using useState with promise just to set value once a good practice?
我想知道在 React 中使用 useState 仅设置一次值是否被认为是一种好的做法,如果不是,如何改进它。
假设我有一个简单的组件,它只是获取一些数据并将它们显示在下拉列表中:
import React, {useState, useEffect} from 'react';
import {utilities} from './utils';
const Component = (props) => {
const [ingredients, setIngredients] = useState([]);
useEffect(() => {
new Promise((resolve, reject) => {
const res = utilities.getIngredients();
if (res.data) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
}).then((response) => {
setIngredients(response);
});
}, []);
return (
<div>
<p>Choose from possible ingredients:</p>
<Select options={ingredients}/>
</div>
);
}
export default Component;
既然setIngredients只调用了一次,那么在这里使用useState是不是太过分了?我的直觉告诉我,可能有更好的方法来做到这一点。另一方面,当我尝试只使用一个变量时,我们没有更新值并且下拉列表没有显示任何选项(这是有道理的,因为数据是在呈现下拉列表之后到达的)。
能否请您判断这里有哪些地方可以改进?
State 在需要持久性 跨渲染 时使用。如果您的组件被重新渲染(反应决定何时发生),未解决的承诺(如 Axios 使用的承诺或在您的问题示例中使用的承诺)仍然会解决并可以为变量赋值 - 但这些变量实际上并没有不再存在。当一个函数组件被重新渲染时,任何声明的变量都会被初始化,就好像这是函数组件的第一个运行(它实际上只是一个函数)。 Promise 持有的任何对“普通”变量的引用(以传统方式 let
、const
或 var
声明,而不是通过 React Hooks 声明)将不再与 Promise 使用的变量相同下一个 运行.
上的函数组件
举个例子来说明:
const Component = (props) => {
let nonStateIngredients = []; //will get initialised to [] every render
useEffect(() => {
doSomethingThatTakesAWhile()
.then((response) => {
// If the Component has been re-rendered
// by the time we get here, the next line will not
// do anything
nonStateIngredients = response.ingredients;
// If not, the above line will work,
// but as soon as we rerender, it will be reinitialised
// to []
});
}, []);
任何不属于 React Hook 的部分都将被重新初始化。
因此,在 React 中,我们使用:
- 用于存储数据的“普通”(
let
、const
)变量派生自渲染中的现有状态或道具,或者在组件的生命周期内保持不变
- 用于存储必须跨渲染持续存在的数据的状态(可以随时间变化的数据)
- Memos(或 Memoized 变量)存储始终派生的数据,但派生成本高(需要大量处理能力)(这是“普通”变量的优化)
为了更直接地回答您的问题,当我们使用 State 检索和分配值时,这不是最佳实践 - 这是唯一可行的方法。
我想知道在 React 中使用 useState 仅设置一次值是否被认为是一种好的做法,如果不是,如何改进它。
假设我有一个简单的组件,它只是获取一些数据并将它们显示在下拉列表中:
import React, {useState, useEffect} from 'react';
import {utilities} from './utils';
const Component = (props) => {
const [ingredients, setIngredients] = useState([]);
useEffect(() => {
new Promise((resolve, reject) => {
const res = utilities.getIngredients();
if (res.data) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
}).then((response) => {
setIngredients(response);
});
}, []);
return (
<div>
<p>Choose from possible ingredients:</p>
<Select options={ingredients}/>
</div>
);
}
export default Component;
既然setIngredients只调用了一次,那么在这里使用useState是不是太过分了?我的直觉告诉我,可能有更好的方法来做到这一点。另一方面,当我尝试只使用一个变量时,我们没有更新值并且下拉列表没有显示任何选项(这是有道理的,因为数据是在呈现下拉列表之后到达的)。 能否请您判断这里有哪些地方可以改进?
State 在需要持久性 跨渲染 时使用。如果您的组件被重新渲染(反应决定何时发生),未解决的承诺(如 Axios 使用的承诺或在您的问题示例中使用的承诺)仍然会解决并可以为变量赋值 - 但这些变量实际上并没有不再存在。当一个函数组件被重新渲染时,任何声明的变量都会被初始化,就好像这是函数组件的第一个运行(它实际上只是一个函数)。 Promise 持有的任何对“普通”变量的引用(以传统方式 let
、const
或 var
声明,而不是通过 React Hooks 声明)将不再与 Promise 使用的变量相同下一个 运行.
举个例子来说明:
const Component = (props) => {
let nonStateIngredients = []; //will get initialised to [] every render
useEffect(() => {
doSomethingThatTakesAWhile()
.then((response) => {
// If the Component has been re-rendered
// by the time we get here, the next line will not
// do anything
nonStateIngredients = response.ingredients;
// If not, the above line will work,
// but as soon as we rerender, it will be reinitialised
// to []
});
}, []);
任何不属于 React Hook 的部分都将被重新初始化。
因此,在 React 中,我们使用:
- 用于存储数据的“普通”(
let
、const
)变量派生自渲染中的现有状态或道具,或者在组件的生命周期内保持不变 - 用于存储必须跨渲染持续存在的数据的状态(可以随时间变化的数据)
- Memos(或 Memoized 变量)存储始终派生的数据,但派生成本高(需要大量处理能力)(这是“普通”变量的优化)
为了更直接地回答您的问题,当我们使用 State 检索和分配值时,这不是最佳实践 - 这是唯一可行的方法。