使用反应挂钩更改嵌套接口的值

Changing values of nested interfaces with react hooks

我想创建一个可以更新导入的嵌套配置文件的应用程序(类似于 swagger)。

我创建了一个 json 配置文件,并在 https://transform.tools/json-to-typescript

的帮助下为其生成了接口

然后我导入原始的 json 配置文件,将其转换为嵌套接口并将其传递给 useState 挂钩。问题是,我如何从应用程序更新单个值?

interfaces.ts

export interface Config {
  project_info: ProjectInfo
  modules: Module[]
}

export interface ProjectInfo {
  go_version: number
  name: string
  port: number
}

Homepage.tsx

import React, { useState, useReducer } from "react"
import { Module, Endpoint, UrlParam, Body, Config, ProjectInfo } from "../interfaces"
import Header from "./Header"

import json_config from "../../../config.json"

export const Homepage = () => {

  // used to filter the selected module
  const [currentlySelectedModule, setCurrentlySelectedModule] = useState("")

  // import json file and convert it to the nested interface
  const placeholder_config: Config = JSON.parse(JSON.stringify(json_config))

  // convert the imported json config to hook, that has the form of generated interface
  const [config, setConfig] = useState<Config>(placeholder_config)

  return (

          <div className="code py-14 grid gap-14 mb-30">
            <div>
              <div className="fs-7 fw-700">ProjectInfo</div>
              <div className="">
                <div>project_name :{config.project_info.name}</div>
                <div>
                  project_name:
                  <input
                    className="module__endpoint_value_input endpoint__input_url"
                    value={config.project_info.name}
                    type="text"
                    // onChange={(e) => setConfig((e) => (config.project_info.name = e.target.value))}
                    // onChange={(e) => setPlaceholderConfig(() => config.project_info.name = e.target.value)}
                  />
                </div>
                <div>go_version :{config.project_info.go_version}</div>
                <div>port :{config.project_info.port}</div>
              </div>
            </div>
          </div>
)
}

所以我正在发送整个配置文件,但想更改嵌套接口值。

在这种情况下,我如何更新 ProjectInfo.name? 此外,useState 是这种情况下的最佳挂钩吗?

感谢帮助。

您的代码中有两个相当大的错误:

  • 传递给 setConfig 的回调未返回新配置
  • 状态是突变在此回调

您可以像这样为您的配置实现自定义挂钩:

import { useState } from 'react';

function useConfig(props) {
    const [config, setConfig] = useState(props.config);

    // Setter for config.project_info.name
    // for other properties there should be other setters
    const setProjectName = (name) => {
        setConfig((config) => ({
            // Should copy every level of data structure manually
            ...config,
            project_info: {
                ...config.project_info,
                name
            }
        }))
    }

    return {
        config,
        setProjectName
    }
}

然后在你的组件中使用它:

import json_config from "../../../config.json"

const Homepage = () => {
    const { config, setProjectName } = useConfig({ config: json_config });

    const handleNameChange = (event) => {
        setProjectName(event.currentTarget.value)
    }

    return (
        <input
            type="text"
            value={config.project_info.name}
            onChange={handleNameChange}
        />
    )
}

如果您不想手动复制深层嵌套对象,您可以使用 Immer, which allows you to write "mutating" code, but not actually mutate it. Other option is to use reactive state management library like MobX.

这样的库