gpt4 book ai didi

ReactJS 访问渲染组件的 Props

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

我正在构建一个将用于逐步过程的组件,例如:

enter image description here

这个Workflow组件采用 array将“步骤”作为 Prop ,然后完成其余的工作。以下是上图中的调用方式:

let steps = [
{
display: "Sign Up Form",
component: SignupForm
},
{
display: "Verify Phone",
component: VerifyPhone
},
{
display: "Use Case Survey",
component: UseCase
},
{
display: "User Profile",
component: UserProfile
},
];

return (
<Workflow
steps={steps}
/>
);

component字段指向该步骤中要渲染的组件。例如SignupForm组件看起来像这样:

export default class SignupForm extends React.Component {
...
render() {
return (
<div>
<div className="page-header">
<h1>New User Sign Up Form</h1>
<p>Something here...</p>
</div>

<div className="form-group">
<input type="email" className="form-control" placeholder="Email address..." />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
</div>
);
}
}

我面临的问题是,每一步都需要有一个 Next按钮验证该步骤中的信息并转到下一步。我本来打算将该按钮放在每个步骤的组件内,但这使其不太用户友好。当用户单击“下一步”并且一切都有效时,该步骤应折叠并打开下一步。然而这意味着我的Workflow组件需要渲染这个按钮。

所以,我需要我的Workflow组件调用每个步骤组件的方法来验证步骤中的信息并返回一个 promise ,让它知道它是通过还是失败(带有任何错误消息)。我需要如何调用这个方法?这里是 Workflow组件渲染所有步骤 如<step.component {...this.props} /> :

{
this.state.steps.map((step, key) => {
return (
...
<Collapse isOpen={!step.collapsed}>
<step.component {...this.props} />
<Button color="primary"
onClick={() => this.validate(key)}>Next</Button>
<div className="invalid-value">
{step.error}
</div>
</Collapse>
...
);
})
}

渲染下一个按钮以及 onClick 处理程序 validate() :

    validate(i) {
let steps = _.cloneDeep(this.state.steps);
let step = steps[i];

step.component.handleNext().then(function () {
...
}).catch((err) => {
...
});
}

理想情况下,step.component.validate()会调用 validate已渲染的组件内的方法:

export default class SignupForm extends React.Component {
....

validate() {
return new Promise((resolve, reject) => {
resolve();
})
}

render() {
...
}
}

.. 可以访问该组件的状态。但是,事情并非如此。我怎样才能让它发挥作用?我读了一些关于转发引用的内容,但不太确定它是如何工作的。非常感谢任何帮助!

最佳答案

一种方法是应用 Observer pattern通过使您的表单成为上下文 Provider并使其提供“注册”功能用于注册Consumers 。您的消费者将是每个 XXXForm 组件。它们都将实现相同的 validate API,因此包装表单可以假设它可以在其注册的任何组件上调用 validate

它可能看起来像下面这样:

const WorkflowContext = React.createContext({
deregisterForm() {},
registerForm() {},
});

export default class Workflow extends React.Component {
constructor(props) {
super(props);
this.state = {
forms: [],
};
}

deregisterForm = (form) => {
this.setState({
forms: this.state.forms.slice().splice(
this.state.forms.indexOf(forms), 1)
});
};

registerForm = (form) => {
this.setState({ forms: [ ...this.state.forms, form ] })
};

validate = () => {
const validationPromises = this.state.forms.reduce(
(promises, formComponent) => [...promises, formComponent.validate()]);
Promise.all(validationPromises)
.then(() => {
// All validation Promises resolved, now do some work.
})
.catch(() => {
// Some validation Promises rejected. Handle error.
});
};

render() {
return (
<WorkflowContext.Provider
value={{
deregisterForm: this.deregisterForm,
registerForm: this.registerForm,
}}>
{/* Render all of the steps like in your pasted code */}
<button onClick={this.validate}>Next</button
</WorkflowContext.Provider>
);
}
}

// Higher-order component for giving access to the Workflow's context
export function withWorkflow(Component) {
return function ManagedForm(props) {
return (
<WorkflowContext.Consumer>
{options =>
<Component
{...props}
deregisterForm={options.deregisterForm}
registerForm={options.registerForm}
/>
}
</WorkflowContext.Consumer>
);
}
}

SignupForm 以及任何其他需要实现验证的表单:

import { withWorkflow } from './Workflow';

class SignupForm extends React.Component {
componentDidMount() {
this.props.registerForm(this);
}

componentWillUnmount() {
this.props.deregisterForm(this);
}

validate() {
return new Promise((resolve, reject) => {
resolve();
})
}

render() {
...
}
}

// Register each of your forms with the Workflow by using the
// higher-order component created above.
export default withWorkflow(SignupForm);

我最初在阅读 react-form's 时发现这种模式适用于 React源码,效果很好。

关于ReactJS 访问渲染组件的 Props,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50331097/

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