Простая проверка форм с использованием хуков, React - PullRequest
0 голосов
/ 11 января 2020

У меня есть предыдущая проверка формы контролируемой формы, и я пытаюсь преобразовать компонент класса в компонент функции с помощью хуков. Но у меня есть проблемы с реализацией оригинальных методов onBlur и onChange. Мой оригинальный код:

import React, {Component} from 'react';
import { Label, Button, Col, Row, FormFeedback, Input, Form } from 'reactstrap';

function SignUp (){
    return(
        <div className="container">
            <div className="row" style={{'padding': '30px 12px 60px 12px'}}>
            <div className="col col-md-8">
                <h4>Inscríbete y crea tu galería de pesonajes!</h4>
            </div>
        </div>
        <div className="row row-content">
            <div className="col col-md-8">
                {<SignUpForm />}
            </div>
        </div>
    </div>
 );
}
class SignUpForm extends Component {

  constructor(props){
      super(props);
  this.state= {
      firstName: '',
      lastName: '',
      email: '',
      username: '',
      pass: '',
      touched:{
        firstName: false,
        lastName: false,
        email: false,
        pass: false,
      }
  }

  this.handleSubmit = this.handleSubmit.bind(this);
  this.handleInput = this.handleInput.bind(this);
  this.handleBlur = this.handleBlur.bind(this);
  }

  handleInput (e) {
    const target = e.target;
    const value = target.type == 'checkbox'? target.checkbox: target.value
    const name = target.name;

this.setState({
    [name]: value,
})
this.setState({username: this.state.email})
  }

  handleBlur = (field) => (e) => {
      this.setState({
          touched : { ...this.state.touched, [field]: true}
      })
  }

  validate (firstName, lastName, email, pass){
  const validEmail = (val) => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(val);
  const errors = {
    firstName: '',
    lastName: '',
    email: '',
    password: ''
  }

    if (this.state.touched.firstName && firstName.length < 2)
        errors.firstName = 'Tu nombre debe tener más de 3 caracteres'

    else if (this.state.touched.firstName && firstName.length > 15)
        errors.firstName = 'Tu nombre debe tener menos de 15 caracteres'

    if (this.state.touched.lastName && lastName.length < 2)
        errors.lastName = 'Tu nombre debe tener más de 3 caracteres'

    else if (this.state.touched.lastName && lastName.length > 15)
        errors.lastName = 'Tu nombre debe tener menos de 15 caracteres'

    if (this.state.touched.email && !validEmail(email))
        errors.email = 'Email No valido'

    else if (this.state.touched.pass && pass.length < 4)
        errors.pass = 'Tu password debe tener más de 3 caracteres'

    return errors
}

 handleSubmit(e) {
    //some fetch operation
  }

render(){
    //const {firstName, lastName, email, pass} = this.state
    const errors = this.validate(this.state.firstName, this.state.lastName, this.state.email, this.state.pass)
    return(
      <Form onSubmit={this.handleSubmit}>
        <Row className="form-group">
          <Label htmlFor="firstname" md={2}><strong>Tu Nombre</strong></Label>
          <Col md={4}>
                <Input type="text" id="firstName" name="firstName"
                  placeholder="Juanito"
                  value={this.state.firstName}
                  className="form-control"
                  valid={errors.firstName === ''}
                  invalid={errors.firstName !== ''}
                  onBlur={this.handleBlur('firstName')}
                  onChange={this.handleInput} />
                <FormFeedback>{errors.firstName}</FormFeedback>
            </Col>
            <Label htmlFor="lastname" md={2}><strong>Tu Apellido</strong></Label>
            <Col md={4}>
              <Input type="text" id="lastName" name="lastName"
                  placeholder="Pérez"
                  value={this.state.lastName}
                  className="form-control"
                  valid={errors.lastName === ''}
                  invalid={errors.lastName !== ''}
                  onBlur={this.handleBlur('lastName')}
                  onChange={this.handleInput} />
                <FormFeedback>{errors.lastName}</FormFeedback>
          </Col>
          </Row>
          <Row className="form-group">
          <Label htmlFor="email" md={2}><strong>Email(*)</strong></Label>
          <Col md={4}>
            <Input type="email" id="email" name="email"
                placeholder="juanito@duck.com"
                className="form-control"
                valid={errors.email === ''}
                invalid={errors.email !== ''}
                onBlur={this.handleBlur('email')}
                onChange={this.handleInput}/>
            <FormFeedback>{errors.email}</FormFeedback>
          </Col>
          <Label htmlFor="password" md={2}><strong>Contraseña</strong></Label>
            <Col md={4}>
                <Input type="password" id="pass" name="password"
                    className="form-control"
                    valid={errors.pass === ''}
                    invalid={errors.pass !== ''}
                    onBlur={this.handleBlur('password')}
                    onChange={this.handleInput} />
                <FormFeedback>{errors.pass}</FormFeedback>
            </Col>
        </Row>
        <Row className="form-group">
          <Col md={{size:2, offset:10}}>
              <Button type="submit" value="submit" name="submit" color="primary">
                  Inscribirse
              </Button>
          </Col>
        </Row>
      </Form>
    )
 }
}

export default SignUp;

И здесь я попытался реализовать то же самое:

import React, { useState } from 'react';
import { Label, Button, Col, Row, FormFeedback, Input, Form } from 'reactstrap';


function SignUp (){
    return(
        <div className="container">
            <div className="row" style={{'padding': '30px 12px 60px 12px'}}>
                <div className="col col-md-8">
                    <h4>Inscríbete y crea tu galería de pesonajes!</h4>
                </div>
            </div>
            <div className="row row-content">
                <div className="col col-md-8">
                    {<SignUpForm />}
                </div>
            </div>
        </div>
    );
}

function SignUpForm() {

    const [formState, setFormState] = useState({firstName: '', lastName: '', email: '', pass: ''})
    const [username, setUsername] = useState('')
    const [touched, setTouched] = useState({firstName: false, lastName: false, email: false, pass: false})

    function handleInput (e) {
        const target = e.target;
        const value = target.type == 'checkbox'? target.checkbox: target.value
        const name = target.name;
        setFormState({ [name]: value })
    }

    function handleBlur(e) { 
        console.log(e.target.name)
        setTouched({...touched, [e.target.name]: true})

    }

    function validate(firstName, lastName, email, pass) {
        const validEmail = (val) => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(val);
        const errors = {
            firstName: '',
            lastName: '',
            email: '',
            password: ''
        }

        if (touched.firstName && firstName.length <= 2)
            errors.firstName = 'Tu nombre debe tener más de 2 caracteres'

        else if (touched.firstName && firstName.length > 15)
            errors.firstName = 'Tu nombre debe tener menos de 15 caracteres'

        if (touched.lastName && lastName.length < 2)
            errors.lastName = 'Tu apellido debe tener más de 3 caracteres'

        else if (touched.lastName && lastName.length > 15)
            errors.lastName = 'Tu apellido debe tener menos de 15 caracteres'

        if (touched.email && !validEmail(email))
            errors.email = 'Email No valido'

        else if (touched.pass && pass.length < 4)
            errors.pass = 'Tu password debe tener más de 3 caracteres'
        return errors
    }

    function handleSubmit(e) {
        //some fetch operation
    }

    const errors = validate(formState.firstName, formState.lastName, formState.email, formState.pass)
    return(
        <Form onSubmit={ () => handleSubmit}>
            <Row className="form-group">
                <Label htmlFor="firstname" md={2}><strong>Tu Nombre</strong></Label>
                <Col md={4}>
                    <Input type="text" id="firstName" name="firstName"
                        placeholder="Juanito"
                        value={formState.firstName}
                        className="form-control"
                        valid={errors.firstName === ''}
                        invalid={errors.firstName !== ''}
                        onBlur={ (e) => handleBlur(e) }
                        onChange={ (e) => handleInput(e) } />
                    <FormFeedback>{errors.firstName}</FormFeedback>
                </Col>
                <Label htmlFor="lastname" md={2}><strong>Tu Apellido</strong></Label>
                <Col md={4}>
                    <Input type="text" id="lastName" name="lastName"
                        placeholder="Pérez"
                        value={formState.lastName}
                        className="form-control"
                        valid={errors.lastName === ''}
                        invalid={errors.lastName !== ''}
                        onBlur={ (e) => handleBlur(e)}
                        onChange={(e) => handleInput(e)} />
                    <FormFeedback>{errors.lastName}</FormFeedback>
                </Col>
                </Row>
                <Row className="form-group">
                <Label htmlFor="email" md={2}><strong>Email(*)</strong></Label>
                <Col md={4}>
                <Input type="email" id="email" name="email"
                    placeholder="juanito@duck.com"
                    value={formState.email}
                    className="form-control"
                    valid={errors.email === ''}
                    invalid={errors.email !== ''}
                    onBlur={ (e) => handleBlur(e)}
                    onChange={(e) => handleInput(e)} />
                <FormFeedback>{errors.email}</FormFeedback>
                </Col>
                <Label htmlFor="password" md={2}><strong>Contraseña</strong></Label>
                <Col md={4}>
                    <Input type="password" id="pass" name="password"
                        value={formState.pass}
                        className="form-control"
                        valid={errors.pass === ''}
                        invalid={errors.pass !== ''}
                        onBlur={ (e) => handleBlur(e)}
                        onChange={(e) => handleInput(e)} />
                    <FormFeedback>{errors.pass}</FormFeedback>
                </Col>
            </Row>
            <Row className="form-group">
                <Col md={{size:2, offset:10}}>
                    <Button type="submit" value="submit" name="submit" color="primary">
                        Inscribirse
                    </Button>
                </Col>
            </Row>
        </Form>
    )
}

export default SignUp;

Когда я начинаю вводить значения во втором поле (фамилия), появляется ошибка с именем «имя» не определено (cannot read length property of undefined). Я думаю, что проблема в том, что setFirstName не может установить значение до функции проверки, но после часовой перестановки кода я не могу найти способ исправить это

1 Ответ

0 голосов
/ 27 марта 2020

Я тоже боролся с этим и хотел бы, чтобы это было помечено как отвеченное, потому что это помогло мне.

Как указывал @VasylButov, setFormState([name]: value) перезаписывает объект formState и устанавливает его в ценность. Сначала используйте оператор распространения ...formState, затем измените требуемое свойство setFormState({...formState, [name]: value}).

Как новый участник SO, я не уверен на 100%, что такое этикет при публикации ответа, который уже был ответил в комментарии, поэтому, пожалуйста, прости меня, если это не правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...