如何命名我的反应组件以容纳嵌套 JSON 中的元素?
Posted
技术标签:
【中文标题】如何命名我的反应组件以容纳嵌套 JSON 中的元素?【英文标题】:How do I name my react component to accommodate an element in my nested JSON? 【发布时间】:2020-06-10 23:31:38 【问题描述】:我正在使用 React 16.13.0 我有以下组件 (src/containers/FormContainer.jsx) ...
class FormContainer extends Component
constructor(props)
super(props);
this.state =
defaultCountry: 484,
countries: [],
provinces: [],
newCoop:
name: '',
type: '',
...
,
...
render()
return (
<form className="container-fluid" onSubmit=this.handleFormSubmit>
<Input inputType='text'
title= 'Name'
name= 'name'
value=this.state.newCoop.name
placeholder = 'Enter cooperative name'
handleChange = this.handleInput
/> /* Name of the cooperative */
<Input inputType='text'
title= 'Type'
name= 'type'
value=this.state.newCoop.type
placeholder = 'Enter cooperative type'
handleChange = this.handleInput
/> /* Type of the cooperative */
我的输入组件,src/components/Input.jsx,看起来像这样......
import React from 'react';
const Input = (props) =>
return (
<div className="form-group">
<label htmlFor=props.name className="form-label">props.title</label>
<input
className="form-input"
id=props.name
name=props.name
type=props.type
value=props.value
onChange=props.handleChange
placeholder=props.placeholder
/>
</div>
)
export default Input;
问题是我需要提交一个 POST 请求,其中“type”参数提交为以下 JSON ...
"name": "1872",
"type":
"name": "Coworking Space"
,
...
如何命名我的第二个输入字段(“类型”字段),以便我可以提交具有正确结构的 JSON?
编辑:句柄输入和提交函数...
handleFormSubmit(e)
e.preventDefault();
let coopData = this.state.newCoop;
fetch('/coops/',
method: "POST",
body: JSON.stringify(coopData),
headers:
'Accept': 'application/json',
'Content-Type': 'application/json'
,
).then(response =>
response.json().then(data =>
console.log("Successful" + data);
)
)
handleClearForm()
// Logic for resetting the form
handleInput(e)
let value = e.target.value;
let name = e.target.name;
this.setState( prevState => ( newCoop :
...prevState.newCoop, [name]: value
), () => console.log(this.state.newCoop))
【问题讨论】:
最简单的方法是更改handleFormSubmit
中的数据形状。你也可以分享那个代码吗?
@bamse,将功能添加为我的问题的编辑
【参考方案1】:
有更多方法可以实现这一点,但我发现有两种方法可以实现
1。将 newCoop
保留在 POST 调用所需的结构中
this.state =
newCoop:
name: '',
type:
name: ''
改变你给类型输入的值
<Input inputType='text'
title= 'Type'
name= 'type'
value=this.state.newCoop.type.name
placeholder = 'Enter cooperative type'
handleChange = this.handleInput
/>
并调整this.handleInput
来处理这种情况:
handleTypeNameChange
函数
更改this.handleInput
,使其能够处理这种情况
这取决于你的this.handleInput
功能 - 你能分享一下吗?
您输入的name
是html name
属性。不确定您是否在handleInput
中使用它。
2。保留表单,因为它是this.handleFormSubmit
中数据形状变化的句柄
this.handleFormSubmit = () =>
const postData =
name: this.state.newCoop.name,
type:
name: this.state.newCoop.type
// POST postData
同样,这取决于您的handleFormSubmit
代码。
希望对你有帮助!
关于选项 1 的更多详细信息:
我喜欢这种方法。 @heisenberg 为此提出了一个解决方案,但不能很好地扩展 - 它可以工作,但是添加更多字段会使该代码变得难以阅读和维护。
你可以:
* 使用要更新的状态值的路径作为输入名称
* 在handleInput
中,您更新位于name
指定路径中的状态值
你可以这样写handleInput
:
import set from "lodash";
[...]
handleInput = e =>
let value = e.target.value;
let name = e.target.name;
const newCoop = set(this.state.newCoop, name, value);
this.setState( newCoop );
;
我为此使用了 lodash 的 set。还有其他方法可以做到这一点 - 如果您真的不想要额外的依赖项,您甚至可以自己编写它。
为了让 newCoop.type.name
工作,您必须调整输入的名称
<input
...
name="type.name" // <- use the path to the value you want to change
value=this.state.newCoop.type.name
...
/>
Here 是一个带有工作示例的 Codesandbox。为简单起见,我使用了常规的 input
,而不是组件。
【讨论】:
我喜欢您在此处的第一个建议中所说的话(保留 POST 调用的结构),因此我进行了更改以将类型值设置为“this.state.newCoop.type.name” ,但是当提交 POST 请求时,类型仍然以 'type: "myType"' 的形式提交,而实际需要提交的方式是 'type: name: "myType"'。【参考方案2】:您必须在this.handleFormSubmit
方法中形成对象,这很容易,您只需根据您的要求形成对象。
handleFormSubmit = () =>
//form json object as per required structure
const formData=
name: this.state.newCoop.name,
type:
name: this.state.newCoop.type
// then send formData in axios or fetch ajax method.
更新
我同意 @bamse 关于 scalibilty 的观点,现在我更改了解决方案以实现更好的缩放。
在此解决方案中,无需安装任何其他软件包。
您只需要再添加一个函数即可从输入组件中读取name
,您可以在其中以点分格式分配name:"type.name"
。
handleInput = (e) =>
let self=this
let value = e.target.value;
let name = e.target.name;
//update State
this.setValue(self.state.newCoop,name,value)
setValue = (obj,is, value) =>
if (typeof is == 'string')
return this.setValue(obj,is.split('.'), value);
else if (is.length==1 && value!==undefined)
return this.setState(obj: obj[is[0]] = value);
else if (is.length==0)
return obj;
else
return this.setValue(obj[is[0]],is.slice(1), value);
输入组件更改:name= 'type.name'
----------------------------------------------END- ----------------------------------------------------
你没有在你的结构中得到 Object 的原因是,你在 INPUT 组件中给出了name= 'type'
。
所以当您在handleInput
方法中处理类型输入字段时,let name = e.target.name;
是"type"
。
当您在...prevState.newCoop, [name]: value
中设置状态时。这里[name]
是"type"
,这是newCoop
的关键。所以它会直接更新type
键。因为您在 INPUT 组件中传递了name= 'type'
【讨论】:
嗨@heisenberg,现在我的 fetch/Ajax 调用中有“body: JSON.stringify(coopData)”。我会继续对您创建的 formData JSON 使用那个“stringify(data)”方法吗? 嗨@Dave,是的,您必须在使用 fetch 时对正文中的数据进行字符串化,否则数据将以 [object] 格式发送。如果您使用 axios 调用,则不必对数据进行字符串化。与 fetch 相比,axios 调用很干净。您可以访问npmjs.com/package/axios。 谢谢。该表单似乎以正确的 JSON 格式提交,但是,我注意到的一件事是无法在地址字段中输入值,例如“街道”。每当我在那里输入时,字符都不会出现。它们显示在其他字段中,例如“名称”或“网站”。如果你有兴趣,这里是完整的代码——github.com/chicommons/maps/tree/master/client 嗨@Dave,我看过你的代码。几乎没有错误。我在 FormContainer.jsx 中做了一些更改。我提供了两种在状态中设置数据的方法。第二种方式是在 FormContainer_2.jsx 文件中。您可以浏览这两个 formContainer 文件。希望你喜欢。谢谢。该链接是这里的邮政编码drive.google.com/open?id=1UCQzk4oG3UnXGbCbTAEUz6jlUl-outag以上是关于如何命名我的反应组件以容纳嵌套 JSON 中的元素?的主要内容,如果未能解决你的问题,请参考以下文章
动态嵌套反应形式:ExpressionChangedAfterItHasBeenCheckedError