我正在使用 React 编写一个 Web 应用程序。 在我的代码中,我对数据库有很多不同的调用。 所有这些调用看起来都非常相似。 唯一的区别是表名称和参数,因此我有很多获取数据的函数。
出于这个原因,我认为我将编写一个通用挂钩来处理我的所有 API 调用。
钩子看起来像这样:
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState({
status: "pending",
value: []
});
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return {
status: "success",
value: response}
});
});
request.send();
});
}, []);
return { value: value, setValue: setValue };
}
然后在代码中我这样使用它:
import { FetchUsers } from '@/app/lib/fetch-users.js';
import { useAWSGenericRequest } from '@/app/ui/hooks/use-aws-generic-request.js'
.
.
.
export default function ListOfUsers(props) {
const users = useAWSGenericRequest(FetchUsers);
.
.
.
return (users.value.value.data.Users.map(function(user, i)
=> return (<div key={i}>{user.email}</div>)));
}
这段代码经过简化,但它描述了我遇到的问题。 一旦“users.value.value.data.Users”更改,我的 API 响应“users.value.value.data.Users”的嵌套结构会导致我的用户界面不再响应。 我在互联网上读到,反应不会对嵌套数组的更改做出反应。
一个解决方案是修改我之前提到的通用钩子,使其看起来像这样:
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState([]);
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return response.value.data.Users);
});
request.send();
});
}, []);
return [value, setValue];
}
然后在代码中我可以这样使用它:
import { FetchUsers } from '@/app/lib/fetch-users.js';
import { useAWSGenericRequest } from '@/app/ui/hooks/use-aws-generic-request.js'
.
.
.
export default function ListOfUsers(props) {
const [users, setUsers] = useAWSGenericRequest(FetchUsers);
.
.
.
return (users.map(function(user, i)
=> return (<div key={i}>{user.email}</div>)));
}
在这种情况下,每次我更改“users”数组时,React 都会做出反应并重新加载用户界面。
问题显然是,如果我想获取其他值,那么我需要复制我的钩子并替换虚线路径以获取我感兴趣的资源,如本示例响应所示。value.some.other.value :
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState([]);
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return response.value.some.other.value);
});
request.send();
});
}, []);
return [value, setValue];
}
我觉得我错过了一些非常简单的技巧/模式,但我只是不知道它是什么。 有没有办法像我一样创建一个通用钩子,或者我是否需要接受为每个新 API 调用创建新钩子的事实?
致以诚挚的问候
问题可能出在你稍后修改对象属性的代码中(你还没有提供该代码,但你在评论中说你稍后要修改
users.value.value.data.Users
)。
您不应该直接修改对象属性。如果您这样做,React 不会知道该更改,也不会重新渲染,从而使您的组件处于过时的状态。 React 状态应该始终是不可变的,以便 React 可以对变化做出反应。例如。使用来自某个
set...
钩子的 useState
函数来更改任何状态(您的称为 setValue
)。
即要么在每次更改时用新对象替换整个对象(整个对象一个
useState
),或者将实际需要的所有值提取到多个 React 状态(每个值一个 useState
)。
您仍然可以将代码分为通用部分和特定部分。如果您难以决定如何做,我建议您尝试几种方法,例如实际上写一些你想避免的钩子。然后你可能会更清楚地看到它们的共同点以及可以概括的内容。