可重用的 React hook 与复杂的 javascript 响应结构

问题描述 投票:0回答:1

我正在使用 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 调用创建新钩子的事实?

致以诚挚的问候

reactjs next.js react-hooks
1个回答
0
投票

问题可能出在你稍后修改对象属性的代码中(你还没有提供该代码,但你在评论中说你稍后要修改

users.value.value.data.Users

您不应该直接修改对象属性。如果您这样做,React 不会知道该更改,也不会重新渲染,从而使您的组件处于过时的状态。 React 状态应该始终是不可变的,以便 React 可以对变化做出反应。例如。使用来自某个

set...
钩子的
useState
函数来更改任何状态(您的称为
setValue
)。

即要么在每次更改时用新对象替换整个对象(整个对象一个

useState
),或者将实际需要的所有值提取到多个 React 状态(每个值一个
useState
)。

您仍然可以将代码分为通用部分和特定部分。如果您难以决定如何做,我建议您尝试几种方法,例如实际上写一些你想避免的钩子。然后你可能会更清楚地看到它们的共同点以及可以概括的内容。

© www.soinside.com 2019 - 2024. All rights reserved.