使用反应挂钩更改嵌套接口的值
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.
这样的库
我想创建一个可以更新导入的嵌套配置文件的应用程序(类似于 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.
这样的库