1.我的意图:
使用
useEffect()
钩子从props中初始化组件的状态变量,它的数据是使用以下命令从firebase中提取的
mapStateToProps()
..。
2.问题:无法初始化组件的状态变量
这个想法是,当组件挂载时,useEffect将只运行一次。在这个初始化窗口中,我希望将数据从firebase加载到该组件的本地状态变量。
它在以下情况下工作得很好
运行本教程中的示例
..。在其中,他使用axios()在
异步/等待
函数。有关他的代码,请参阅下面的第3节。
但当我这样做时,试图从props获取数据,而props是与Firestore同步或由Firestore初始化的,我总是得到null,无法从
从我的async/await函数返回。
我想这是因为我对async/await缺乏理解。我无法创建有效的
异步/等待
函数从props中检索数据。
问题:
我怀疑这就是问题所在。那么,什么才是编写
异步/等待
哪个函数可以正确地从与firebase同步的道具中检索数据?
我的问题代码:
import React, { useState, useEffect} from "react";
import { connect } from "react-redux";
import { firestoreConnect } from "react-redux-firebase";
import { compose } from "redux";
const app = props => {
const { order } = props;
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async () => {
const result = await (() => {
return new Promise(resolve => {
if (order) { resolve(order); }
});
})();
setData(result);
};
fetchData();
}, []);
/** if I leave useEffect's second argument empty, which is intended to run only once at the beginning, then i'm getting null */
...
const mapStateToProps = state => {
const id = "DKA77MC2w3g0ACEy630g"; // docId for testing purpose.
const orders = state.firestore.data.orders;
const order = orders ? orders[id] : null;
return {
order: order
};
};
export default compose(
connect(mapStateToProps),
firestoreConnect([{collection: "orders"}])
)(app);
我尝试过的:
如果我添加
订单
添加到第二个参数中,那么它将正确地将数据加载到组件的状态变量中。但它会将道具的数据重新加载到组件的状态变量中,并在每个重新渲染周期中擦除任何更改。
useEffect(() => {
...
}, [order]);
是
mapStateToProps()
在初始组件挂载后发生?因为这将解释为什么在最初的效果中,道具总是空的。
3.我遵循的教程:使用钩子获取数据
我能够使用以下命令成功获取数据
本教程中的技术
:
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
const result = await axios(
"https://hn.algolia.com/api/v1/search?query=redux"
);
setData(result.data);
};
fetchData();
}, []);
发布于 2021-02-10 09:21:49
听起来像是
可以是父级每次创建的对象。钩子依赖关系检查是否完全匹配--
--因此,即使对象内部的值不变,如果对象本身发生变化,效果也会再次运行。
最常见的方式是传递普通的对象文字:
const order = { id: 'foo', SKU: 'bar', cost: 19.95, quantity: 1 };
return ;
这将重新填充
每次都使用新的对象字面量。当您将一个对象扩展到另一个对象中时,会出现更隐蔽的重新创建文字的情况:
const order = { ...oldOrder, quantity: 2 };
这仍然会创建一个新对象。
不要试图改变现有的对象。
React会开始对你做非常奇怪的事情。一旦你理解了钩子依赖是如何工作的,变异的对象就会让你陷入困境。
您有三种选择:
使用原语作为依赖项
如果你能找出
应该
从服务器强制刷新,将其放入其自己的变量中,并根据该变量设置依赖项。只有当您只需要向服务器发送有限数量的字段时,这才能很好地工作。
如果,在您的示例中,您只需要订单的
要进行调用,您可以将其提取到它自己的变量中:
const orderId = order.id;
useEffect(() => {
const fetchData = async () => {
const response = await axios(`url-with-id?orderId=${orderId}`);
setData(response.data);
};
fetchData();
}, [orderID]);
请注意,如果您尝试访问整个
对象,即使你没有将它包含在依赖数组中,React也会报错,这是有充分理由的。除非你能绝对保证它永远不会改变,除非
也会改变,它可能会导致运行时错误,这些错误将在以后攻击您。只能在效果中使用依赖数组中的内容。
记忆你的对象
如果你的
对象非常简单,你可以根据它的内容来记忆它。
以同样的方式获取依赖项数组
这样做,但不是在依赖项发生变化时运行效果,
每当依赖项发生更改时,都会返回一个新对象。
只要没有任何依赖关系改变,
返回相同的对象。
这就是为什么它有效的关键。
如果
有几个简单的值,例如
,以及
,您可以将您的对象文字创建更改为如下所示:
const order = useMemo(
() => ({
id,
SKU,
price,
quantity
}),
[id, SKU, price, quantity]
);
现在,只要没有任何数字或字符串
更改,则每次渲染都将获得相同的对象。因为它是同一个物体,
将只运行一次。如果其中一个值发生更改,则新的
对象将被提供,
的依赖关系数组被更改,并为新的
..。
查看一下为什么你会不断更新
对象
在你的情况下,看起来你得到了你的
来自Redux存储的对象。Redux依赖于它的数据只有在必要的时候才会改变。每次Redux中的数据发生更改时,都会触发每个需要它的组件中的更改。如果数据发生了不必要的更改,这可能会导致您获取不断更新的对象。
您需要查看是否有另一个组件将不必要的操作分派到Redux,或者您的reducer是否在不需要时意外地创建了所有新对象。家长是否在没有检查是否需要的情况下进行更新?您是否有异步操作(thunks或sagas)对您的数据存储进行大量更新?在简单地在旧数据之上写入新数据之前,您是否检查了传入数据和现有数据之间的增量?
Redux状态管理本身就是一个完整的主题。它可能更容易使用
Redux工具包
也不愿自己动手。它负责需要在存储中重新创建的内容,而不必管理不变性问题。如果FireBase数据故意覆盖你的数据,Redux Toolkit可能会让你更容易确保只更新在调用之间更改的数据,而不是一直在更改所有数据。
发布于 2020-12-26 02:28:18
试试这个:
const app = props => {
const [data, setData] = useState({ results: [] });
useEffect(() => {
const getData = async () => {
const result = await axios('Your URL here');
setData(result.data);
};
getData();
}, []);
...
发布于 2021-03-01 17:05:50
试试这个:
const app = props => {
const [data, setData] = useState({ results: [] });
const getData = async () => {
const result = await axios('Your URL here');
setData(result.data);
};
useEffect(() => {
getData();
}, []);
...
}
https://stackoverflow.com/questions/58227421
复制相似问题