javascript - 将值从自定义挂钩保存到状态
问题描述
我正在尝试使用 useState 将自定义挂钩中的值保存到功能组件状态,该挂钩正在为服务器获取数据,因为我稍后需要更改此值,并且在更改后需要重新渲染。所以期望的行为是:
- 将状态变量设置为自定义挂钩的值
- 用这个状态变量渲染东西
- 修改按钮点击状态
- 使用新状态重新渲染
我尝试的是:
将 useState 的初始值设置为我的钩子:
const [data, setData] = useState<DataType[] | null>(useLoadData(id).data)
但数据始终为空。在 useEffect() 挂钩中设置状态:
useEffect(()=>{ const d = useLoadData(id).data setData(d) }, [id])
但这向我显示了错误警告:错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。
这样做:
const [data, setData] = useState<DocumentType[]>([]) const dataFromServer = useLoadData(id).data useEffect(()=>{ if (dataFromServer){ setData(dataFromServer) } }, [dataFromServer])
导致:错误:超出最大更新深度。当组件在 useEffect 中调用 setState 时,可能会发生这种情况,但 useEffect 要么没有依赖数组,要么每次渲染时依赖项之一发生变化。
对于我的用例,什么是合适的解决方案?
解决方案
看起来您的自定义挂钩每次使用时都会返回一个新数组。
解决方案 1:更改您的挂钩以返回数组的“缓存”实例。
function useLoadData(id) {
const [data, setData] = useState([]);
useEffect(() => {
loadData(id).then(setData);
}, [id]);
// good
return data;
//bad
//return data.map(...)
//bad
//return data.filter(...)
//etc
}
解决方案 2:更改您的挂钩以接受setData
作为参数。
function useLoadData(id, setData) {
useEffect(() => {
loadData(id).then(setData);
}, [id]);
}
在这里,我要告诉钩子在哪里存储数据,以便自定义钩子和组件中的按钮都可以写入同一个地方。
完整示例:
import React from "react";
import ReactDOM from "react-dom";
import { useState, useEffect } from "react";
// simulates async data loading
function loadData(id) {
return new Promise((resolve) => setTimeout(resolve, 1000, [id, id, id]));
}
// a specialized 'stateless' version of custom hook
function useLoadData(id, setData) {
useEffect(() => {
loadData(id).then(setData);
}, [id]);
}
function App() {
const [data, setData] = useState(null);
useLoadData(123, setData);
return (
<div>
<div>Data: {data == null ? "Loading..." : data.join()}</div>
<div>
<button onClick={() => setData([456, 456, 456])}>Change data</button>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("container"));
推荐阅读
- node.js - 无法获取特定路线
- ios - Apple 商店要求 {mediaType: 'photo'} 中的音频权限
- excel - 一个单元格中的不同格式 - Excel Web
- javascript - 如何使用 gmail api 获取新消息
- javascript - cytoscape.js 在一个元素上的相同/不同事件类型上是否有稳定的事件排序?
- ckeditor - 当我尝试从 ckeditor 导入时“未找到此依赖项”
- javascript - Chart.JS:在圆环图上永久显示自定义标签
- protractor - 是否存在与 Cypress 功能类似的量角器工具?
- grammar - 如何将 Grammar::Tracer 与单元范围语法一起使用?
- java - Tomcat LifeCycle 异常 LifecycleException: 无法启动组件 [StandardEngine[Catalina].StandardHost[localhost].StandardContext