I asked this question yesterday: React sharing method across components
import React from 'react';
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
const target = e.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
Since I'm reusing handleChange(e)
many times throughout my application, I decided to separate it out into a higher-order component as so:
import React from 'react';
const withHandleChange = (WrappedComponent) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
handleChange = e => {
const target = e.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<WrappedComponent
handleChange={this.handleChange}
form={this.state}
{...this.props}
/>
);
}
}
};
export default withHandleChange;
Instead of making LoginForm
maintain the state of the input fields, I now have the HOC accomplish that, and I pass this state down as a prop called form
. I also pass down the handleChange
method as a prop.
And in the original LoginForm
component, I render the following:
<input type="text" placeholder="Email" name="email" value={this.props.form.email} onChange={this.props.handleChange} />
I wrapped LoginForm
as so:
const WrappedLoginForm = withHandleChange(LoginForm);
const LoginBox = props => (
<div className="login-box">
<WrappedLoginForm />
</div>
);
Is this a valid implementation? My main two concerns are (1) passing down the state as a prop to WrappedComponent
in the withHandleChange
definition, and (2) rendering WrappedLoginForm
since I've read you shouldn't use HOCs inside the render method.
As for (1), is this efficient? Is there a better way to accomplish what I'm doing?
As for (2), I think they meant that I shouldn't run the HOC function inside the render method, but simply using a wrapped component (as I do now) should be fine. However, I'm slightly confused and would appreciate some confirmation.
Any and all suggestions would be helpful. Thanks!
It's disallowed to use HOCs in the render lifecycle because of that below expression
const WrappedLoginForm = withHandleChange(LoginForm);
does declare a component. And you know render lifecycle might be executed more than one time depends on what exactly happens to your app. Then It results to be more than one time that declaration of the wrapped component will be executed which may lead to unexpected behavior. I think this is the root reason why it's disallowed.
To avoid this kind of mistake, it is very recommended to declare the wrapped component at the place the inner component is exported(or imported). Like: LoginForm.js
export default withHandleChange(LoginForm)
or
import LoginForm from 'somewhere'
const WrappedLoginForm = withHandleChange(LoginForm);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.