0
votes

Im my react application, Im in the refactoring phase. I want to separate redux part from the components. Im confused about where to put proptypes validation? Should the redux props be validated in the container file, and component props should be validated on the component? Or should the both prop types be handled on the component? Or in container? Here is my code.

import React, { Component } from 'react';
import { withRouter } from 'react-router-dom'; 

import PropTypes from 'prop-types';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import { registerUser } from '../../../actions';

import { TextFieldGroup } from '../../../components/UI';

class RegisterScreen extends Component {
   state = {
      name: '',
      email: '',
      password: '',
      password2: '', 
      errors: {}
   };

   componentDidMount() {
      if (this.props.auth.isAuthenticated) {
         this.props.history.push('./dashboard');
      }
   }

   componentWillReceiveProps(nextProps) {
      if (nextProps.errors) {
         this.setState({ errors: nextProps.errors });
      }
   }

   onChange = e => {
      this.setState({
         [e.target.name]: e.target.value 
      });
   }

   onSubmit = e => {
      e.preventDefault();

      const newUser = {
         name: this.state.name,
         email: this.state.email,
         password: this.state.password,
         password2: this.state.password2
      }

      this.props.registerUser(newUser, this.props.history);
   } 

   render() {
      const { errors } = this.state;

      return (
         <div className='register'>
            <div className='container'>
               <div className='row'>
                  <div className='col-md-8 m-auto'>

                     <h1 className='display-4 text-center'>Sign Up</h1>

                     <p className='lead text-center'>
                        Create Your Developer Connector Account
                     </p>

                     <form noValidate onSubmit={this.onSubmit}>
                        <TextFieldGroup 
                           className={errors.email}
                           placeholder="* Full Name" 
                           name="name" 
                           value={this.state.name}
                           onChange={this.onChange}
                           error={errors.name}
                        />

                        <TextFieldGroup 
                           type='email'
                           className={errors.email}
                           placeholder="* Email Address" 
                           name="email" 
                           value={this.state.email}
                           onChange={this.onChange}
                           error={errors.email}
                           info='This site uses Gravatar so if you want a profile image, use a Gravatar email'
                        /> 

                        <TextFieldGroup 
                           type='password'
                           className={errors.password}
                           placeholder="* Password" 
                           name="password" 
                           value={this.state.password}
                           onChange={this.onChange} 
                           error={errors.password}
                        /> 

                        <TextFieldGroup 
                           type='password' 
                           className={errors.password2}
                           placeholder="* Confirm Password" 
                           name="password2" 
                           value={this.state.password2}
                           onChange={this.onChange}
                           error={errors.password2}
                        /> 

                        <input type='submit' className='btn btn-info btn-block mt-4' />
                     </form>

                  </div>
               </div>
            </div>
         </div>
      );
   }
}

RegisterScreen.propTypes = {
   registerUser: PropTypes.func.isRequired,
   auth: PropTypes.object.isRequired,
   errors: PropTypes.object.isRequired
} 

const mapStateToProps = state => ({
   auth: state.auth,
   errors: state.errors
});

const mapDispatchToProps = dispatch => ({
   registerUser: bindActionCreators(registerUser, dispatch)
});

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(RegisterScreen));
1
You can defined PropTypes on the component returned by connect - Shubham Khatri
A nice way to avoid this problem is to define your proptypes on Component. you can check this simple example stackblitz.com/edit/react-redux-simple-inputtext-to-list - Jayavel

1 Answers

0
votes

You should define the PropTypes in the component as you have in the example there. When deciding when to use PropTypes for static typing, you should always guard against incoming props that can directly affect the desired result of the component when rendered. By that I mean, if the component requires "auth" or "errors" props, then you should define the PropTypes for the component receiving those properties, whether through HoC in this case redux or any other mode of passing data down.