3 回答
TA贡献1744条经验 获得超4个赞
这是我花了一些时间与自己斗争的问题。有多种方法可以将子状态保持在更高级别;但是,我发现在您的特定情况下,通常最好使用 Redux。
需要明确的是,我通常不惜一切代价避免 Redux(支持 React 的上下文),但 Redux 让您能够订阅子组件中的特定状态。当您只需要更新一个子组件时,侦听子组件中的一个状态将阻止您的父组件和兄弟组件更新。这在一次处理多个表单时效率更高。
例如,以下组件将仅侦听影响其自身状态的状态更新。这些更新将绕过表单父组件和兄弟组件:
import React from 'react';
import { connect } from 'react-redux';
import * as actions from 'redux/actions';
// Custom component
import { InputField } from 'shared';
const FormOne = ({ me, actions }) => (
<form>
<InputField
inputId="f1f1"
label="field one"
value={me.fieldOne}
onChange={(e) => actions.setFormOneFieldOne(e.target.value)}
/>
<InputField
inputId="f1f2"
label="field two"
value={me.fieldTwo}
onChange={(e) => actions.setFormOneFieldTwo(e.target.value)}
/>
<InputField
inputId="f1f3"
label="field three"
value={me.fieldThree}
onChange={(e) => actions.setFormOneFieldThree(e.target.value)}
/>
</form>
);
export default connect(state => ({ me: state.formOne }), actions)(FormOne);
在上面的例子FormOne中只是监听自己的状态更新;然而,使用上下文而不是 Redux 的类似逻辑将导致上下文提供者包装的整个组件树更新(包括父组件和兄弟组件):
import React, { useContext } from 'react';
// Custom component
import { InputField } from 'shared';
// Custom context - below component must be wrapped with the provider
import { FormContext } from 'context';
const FormTwo = () => {
const context = useContext(FormContext);
return(
<form>
<InputField
inputId="f2f1"
label="field one"
value={context.state.formTwo.fieldOne}
onChange={(e) => context.setFormTwoFieldOne(e.target.value)}
/>
<InputField
inputId="f2f2"
label="field two"
value={context.state.formTwo.fieldTwo}
onChange={(e) => context.setFormTwoFieldTwo(e.target.value)}
/>
<InputField
inputId="f2f3"
label="field three"
value={context.state.formTwo.fieldThree}
onChange={(e) => context.setFormTwoFieldThree(e.target.value)}
/>
</form>
);
};
export default FormTwo;
可以对上述两个组件进行一些改进,但它们旨在作为如何将子组件连接到提升状态的示例。也可以使用 连接到单个父组件props,但这是效率最低的选项,并且会使您的体系结构混乱。
关键要点:将 Redux 用于您的用例。如果正确实施,这是最有效的选择。
TA贡献1798条经验 获得超7个赞
提升状态确实是这样做的正确方法。要优化子部分,您可以使用
PureComponent ==> https://reactjs.org/docs/react-api.html#reactpurecomponent
AKA 记忆组件 ==> https://reactjs.org/docs/react-api.html#reactmemo
React.memo 是一个高阶组件。它类似于 React.PureComponent 但用于函数组件而不是类。
此外,如果您在钩子宇宙结帐中
useCallback :https ://reactjs.org/docs/hooks-reference.html#usecallback
使用备忘录: https ://reactjs.org/docs/hooks-reference.html#usememo
如果您有任何机会使用 Redux,请记得查看
TA贡献1805条经验 获得超9个赞
将所有表单包装在一个仅处理保存所有表单数据并运行“全部保存”功能的组件中:
包装器组件应该有一个包含所有表单数据的状态,它应该看起来像这样:
class Wrapper Component extends React.Component {
constructor(props) {
super(props);
this.state = {
formsData: {},
};
}
}
formsData 的结构应该差不多是这样的: { 0: { title:"text", type:"video", etc:"etc" }, 1: { title:"text", type:"video", etc: "etc" }} 键(0,1 等)代表表单 ID,并且可以设置为每个 for 具有的任何唯一修饰符。
然后让包装器组件处理每个单独表单的 onChange -> 每个单独表单上的每次更改都应该提升新状态(新更新的数据)并相应地更新 formsData 状态 obj:
const onChange(formData) {
const formattedData = {[formData.id]: {...formData}}
this.setState({formsData: {...formsData, ...formattedData}})
}
* 这只是一个例子,在每个表单的每次更改中,您都会提升整个数据对象,您可以通过多种方式进行操作
比,保存所有按钮也应该在包装器组件中处理,并将您使用它存储的所有数据提升到父组件中的相关功能/自行处理。
添加回答
举报