gpt4 book ai didi

javascript - 在 React 中通过嵌套组件向上传递数据

转载 作者:行者123 更新时间:2023-12-03 14:30:08 24 4
gpt4 key购买 nike

以一个想法作为开头;我想我可能需要一个递归组件,但这超出了我目前使用原生 js 和 React 的能力,所以我觉得我现在对 React 有了瑞士奶酪的理解。

问题:

我有一个数组 metafields包含metafield具有以下结构的对象:

{
metafields: [
{ 0:
{ namespace: "namespaceVal",
key: "keyVal",
val: [
0: "val1",
1: "val2",
2: "val3"
]
}
},
...
]
}

我的代码映射 metafields放入卡片中,每张卡片内都有一个组件 <MetafieldInput metafields={metafields['value']} />在该组件中,值数组被映射到输入字段。总的来说,它看起来像:

// App
render() {
const metafields = this.state.metafields;
return (
{metafields.map(metafield) => (
<MetafieldInputs metafields={metafield['value']} />
)}
)
}

//MetafieldInputs
this.state = { metafields: this.props.metafields}

render() {
const metafields = this.state;
return (
{metafields.map((meta, i) => (
<TextField
value={meta}
changeKey={meta}
onChange={(val) => {
this.setState(prevState => {
return { metafields: prevState.metafields.map((field, j) => {
if(j === i) { field = val; }
return field;
})};
});
}}
/>
))}
)
}

到目前为止,一切都正确显示,我可以更改输入!然而,这种变化一次发生一个,就像我按下一个键,然后我必须重新单击输入以添加另一个字符。似乎一切都被重新渲染,这就是为什么我必须单击回输入以进行另一次更改。

我可以这样使用组件吗?感觉就像我正在努力嵌套组件,但我读过的所有内容都说不要嵌套组件。我是否把这个问题过于复杂化了?我唯一的解决方案是删除 React 部分并将其转换为纯 JavaScript。

非常感谢指导!

最佳答案

我的建议是外包 onChange 处理程序,这样代码会更容易理解一些。

主要是 React 不会在调用 setState() 后立即更新状态,它会执行批处理作业。因此,可能会发生多个 setState 调用正在访问一个引用点的情况。如果直接改变状态,可能会导致困惑,因为其他状态可以在执行批处理作业时使用更新后的状态。

此外,如果您在应用程序级别外包 onChange 处理程序,则可以将 MetafieldInputs 更改为功能组件而不是基于类的组件。基于功能的组件比基于类的组件成本更低,并且可以提高性能。

下面是经过测试的更新代码。我假设您使用 Material UI 的 TextField,但 onChangeHandler 也应该在您自己的组件中工作。

// Full App.js
import React, { Component } from 'react';
import MetafieldInputs from './MetafieldInputs';

class App extends Component {
state = {
metafields: [
{
metafield:
{
namespace: "namespaceVal",
key: "keyVal",
val: [
{ '0': "val1" },
{ '1': "val2" },
{ '2': "val3" }
]
}
},
]
}

// will never be triggered as from React point of view, the state never changes
componentDidUpdate() {
console.log('componentDidUpdate')
}

render() {
const metafields = this.state.metafields;
const metafieldsKeys = Object.keys(metafields);
const renderInputs = metafieldsKeys.map(key => {
const metafield = metafields[key];
return <MetafieldInputs metafields={metafield.metafield.val} key={metafield.metafield.key} />;
})
return (
<div>
{renderInputs}
</div>
)
}
}

export default App;

// full MetafieldInputs
import React, { Component } from 'react'
import TextField from '@material-ui/core/TextField';

class MetafieldInputs extends Component {
state = {
metafields: this.props.metafields
}

onChangeHandler = (e, index) => {
const value = e.target.value;
this.setState(prevState => {
const updateMetafields = [...prevState.metafields];
const updatedFields = { ...updateMetafields[index] }
updatedFields[index] = value
updateMetafields[index] = updatedFields;
return { metafields: updateMetafields }
})
}

render() {
const { metafields } = this.state;
// will always remain the same
console.log('this.props', this.props)
return (
<div>
{metafields.map((meta, i) => {
return (
<TextField
value={meta[i]}
changekey={meta}
onChange={(e) => this.onChangeHandler(e, i)}
// generally it is not a good idea to use index as a key.
key={i}
/>
)
}
)}
</div>
)
}
}

export default MetafieldInputs

同样,如果您将 onChangeHandler 外包给 App 类,则 MetafieldInputs 可以是纯功能组件,并且所有状态管理都可以在 App 类中完成。

另一方面,如果您想保持一个纯净的 App 类,您还可以将元字段存储到 MetafieldInputs 类中,以防您的应用程序中可能需要一些其他逻辑。

例如,您的应用程序呈现的组件比示例多,并且在发生某些情况之前不应呈现 MetafieldInputs。如果从服务器端获取数据,最好在需要时获取数据,而不是获取App组件中的所有数据。

关于javascript - 在 React 中通过嵌套组件向上传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60081956/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com