0

I am making a form wizard in React Js. In the first step, I want to hide/display a form base on radio input value. I want to set the state of the parent based on the input from a visible form. Basically, I want to check if a user exists or not and then take the appropriate action. If they exist, I enter their username, if not I enter the registration details. Here is my code

class Step1 extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            userExists: 'false',
            username: '',
            register: {
                full_name: '',
                phone_number: '',
                id_number: '',
                gender: ''
            },
            submitted: false,
        }

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleUserExistsCheck = this.handleUserExistsCheck.bind(this);
    }

    handleChange(event) {
        const { name, value } = event.target;
        this.setState({
            [name]: value
        });
    }

    handleUsernameChange(event) {
        const { name, value } = event.target;
        const { username} = this.state;

        this.setState({
            username: username
        });
    }

    handleRegisterChange(event) {
        const { register } = this.state;
        const { name, value } = event.target;

        this.setState({
            register: {
                ...register,
                [name]: value
            }
        });
    }

    handleUserExistsCheck(event) {
        this.setState({
            ...this.state,
            userExists: event.target.value
        });
    }

    handleSubmit(event) {
        event.preventDefault();

        this.setState({
            ...this.state,
            submitted: true
        });

       // TODO: Dispatch based on checkbox
    }

    _validate() {
        let { user } = this.state
        this.props.afterValid({
            // TODO submit data to wizard
        });
    }

    handleReset() {
        this.setState({
            ...this.state,
            userExists: false,
            username: '',
            full_name: '',
            phone_number: '',
            id_number: '',
            gender: '',
            submitted: false,
        });
    }

    render() {
       if (this.props.currentStep !== 1) {
         return null;
       } 

       const { userExists, username, register } = this.state;
       console.log(register)

       return(
            <div>
            <CardHeader>Does the user have an account?</CardHeader>
            <CardBody>
                <form onSubmit={this.handleSubmit}>
                    <div>
                        <input type="radio" value="true" checked={ userExists ==="true"}
                        onChange={this.handleUserExistsCheck} name="userExists"/> Yes
                        {' '} 
                        <input type="radio" value="false"  checked={ userExists ==="false"}
                        onChange={this.handleUserExistsCheck} name="userExists"/> No
                    </div>
                    {' '}
                    <PersonalDetails register={register} 
                    username={username}
                    handleRegisterChange={this.handleRegisterChange} 
                    handleUsernameChange={this.handleUsernameChange}
                    userExists={userExists}/>
                    {' '}
                    <div className="clearfix">
                    <button type="submit" className="btn btn-primary mb-2 float-right">Next</button>
                    </div>
                </form>
            </CardBody>
            </div>
        );
   }
}

function UsernameForm(props) {
    return (
        <FormGroup>
            <label>Username</label>
            <Input type="text" name="username" value={props.username}
            onChange={props.onChange} placeholder="Username"/>
        </FormGroup>
    )
}

function RegisterForm(props) {
     return(
        <div>
        <FormGroup>
            <label>Full Name</label>
            <Input type="text" name="full_name" value={props.register.full_name}
            onChange={props.onChange} placeholder="Full Name"/>
        </FormGroup>
        <FormGroup>
            <label>Phone Number</label>
            <Input type="text" name="phone_number" value={props.register.phone_number}
            onChange={props.onChange} placeholder="Phone Number"/>
        </FormGroup>
        <FormGroup>
            <label>ID Number</label>
            <Input type="text" name="id_number" value={props.register.id_number}
            onChange={props.onChange} placeholder="ID Number"/>
        </FormGroup>
         <FormGroup>
            <label htmlFor="gender">Gender</label>
                <select value={props.register.gender} onChange={props.onChange} 
                    className="custom-select custom-select-lg mb-3" name="gender">
                    <option value="">----</option>
                    <option value="M">Male</option>
                    <option value="F">Female</option>                              
                </select>
        </FormGroup>
        </div>
    );
}

function str2bool(value) {
    if (typeof(value) === 'string') {
        if (value.toLowerCase() === 'true') return true;
        if (value.toLowerCase() === 'false') return false;
    }
    return value;
}


function PersonalDetails(props) {
    let { userExists } = props;
    userExists = str2bool(userExists);

    if (userExists == true) {
        return <UsernameForm username={props.username} onChange={props.handleUsernameChange}/>
    } else {
        return <RegisterForm register={props.register} onChange={props.handleRegisterChange}/>
    }
}

const connectedStep1 = connect(null, null)(Step1);
export { connectedStep1 as Step1 };

Currently, I am getting the error Uncaught TypeError: Cannot read property 'state' of undefined

Grovel Ode
  • 95
  • 1
  • 9
  • @Shubham Khatri Thank you. However when I was refactoring my code, i found out I had not bound the method in the constructor – Grovel Ode Sep 22 '18 at 11:25

1 Answers1

0

Create a method in the parent component to update the state, then pass this method to the child component as a prop. When you call this prop in the child it will update the parent state.