Extracting helper rendering methods

Lebih menyederhanakan lg code

Form.jsx

import React, { Component } from "react";
import Joi from "joi-browser";
import Input from "./Input";

class Form extends Component {
    state = { 
        data: {},
        errors: {}
    };

    validate = () => {
        const options = { abortEarly: false };
        const { error } = Joi.validate(this.state.data, this.schema, options);
        // console.log(result)
        if (!error) return null;

        const errors = {};
        for (let item of error.details) errors[item.path[0]] = item.message;
        return errors;
    };

    validateProperty = ({ name, value }) => {
        const obj = { [name]: value };
        const schema = { [name]: this.schema[name] }
        const {error} = Joi.validate(obj, schema);
        return error ? error.details[0].message : null;
    }

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

        const errors = this.validate();
        // console.log(errors);
        this.setState({ errors: errors || {} })
        if (errors) return;

        this.doSubmit();
    };

    handleChange = ({ currentTarget: input }) => {
        const errors = { ...this.state.errors };
        const errorMessage = this.validateProperty(input);
        if (errorMessage) errors[input.name] = errorMessage;
        else delete errors[input.name];
 
         const data = {...this.state.data};
         data[input.name] = input.value;
         this.setState({ data, errors });
    };
    renderButton(label) {
        return (
            <button disabled={this.validate()} className="btn btn-primary">{label}</button>
        )
    }
    renderInput(name, label, type = "text") {
        const { data, errors } = this.state;

        return (
            <Input 
                type={type}
                name={name}
                value={data[name]}
                label={label}
                onChange={this.handleChange}
                error={errors[name]}
            />
        )
    }
}
 
export default Form;

LoginForm.jsx

import React, { Component } from "react";
import Joi from "joi-browser";
import Form from "./Common/Form";

class LoginForm extends Form {
    state = {
        data : {
            username: '',
            password: ''
        },
        errors: {}
    };

    schema = {
        username: Joi.string().required().label("Username"),
        password: Joi.string().required().label("Password")
    };
    
    doSubmit = () => {
        // Call the server
        console.log("submit");
    }

    render(){
        return (
            <>
                <div>
                    <h1>Login</h1>
                    <form onSubmit={this.handleSubmit} >
                        {this.renderInput('username', 'Username')}
                        {this.renderInput('password', 'Password', "password")}
                        {this.renderButton('Login')}
                    </form>
                </div>
            </>
        )
    }
}

export default LoginForm

Input.jsx

import React from "react";

const Input = ({ name, label, error, ...rest }) => {
    return (
        <>
            <div className="form-group">
                <label htmlFor={name}>{ label }</label>
                    <input
                        {...rest}
                        name={name}
                        id={name} 
                        className="form-control" 
                    />
                    { error && <div className="alert alert-danger">{error}</div> }
            </div>
        </>
    )
}

export default Input;

Last updated

Was this helpful?