Обновление prop для определенного компонента на основе ответа API

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть API, который с объектом и инкапсулирует ошибки, связанные с каждым полем ввода внутри него, например:

 {
"success": false,
"message": "The given data was invalid.",
"errors": {
    "firstname": [
        "Invalid firstname", 
        "Firstname must be at least 2 characters long"
    ], 
    "companyname": ["company name is a required field"]
   }
}
  

на основе ошибок мне нужно отобразить ошибку прямо под элементом ввода, для которого код выглядит следующим образом:

     class RegistrationComponent extends  Component {

      onSubmit = (formProps) => {

         this.props.signup(formProps, () => {
           this.props.history.push('/signup/complete');
         });
      };

    render() {
        const {handleSubmit} = this.props;
        return (
            <div>
                <form
                  className='form-signup'
                  onSubmit={handleSubmit(this.onSubmit)}
                >
              <Field name='companyname' type='text' component={inputField} className='form-control' validate={validation.required} />
              <Field name='firstname' type='text' component={inputField} className='form-control' validate={validation.required} />
<Translate
                    content='button.register'
                    className='btn btn-primary btn-form'
                    type='submit'
                    component='button'
                  />
                </form>
            </div>
      );}}
  

Входное поле:

 export const inputField = ({
  input,
  label,
  type,
  className,
  id,
  placeholder,
  meta: { error, touched },
  disabled
}) => {
  return (
    <div>
      {label ? (
        <label>
          <strong>{label}</strong>
        </label>
      ) : null}
      <Translate
        {...input}
        type={type}
        color={"white"}
        className={className}
        id={id}
        disabled={disabled}
        component="input"
        attributes={{ placeholder: placeholder }}
      />
      <InputFieldError
        touched={touched}
        error={<Translate content={error} />}
      />
    </div>
  );
};
  

и, наконец,;

 import React, { Component } from "react";

class InputFieldError extends Component {
  render() {
    return <font color="red">{this.props.touched amp;amp; this.props.error}</font>;
  }
}

export default InputFieldError;
  

Если я просто проверю с помощью validate={validation.required} , свойство error будет привязано к правильному полю ввода, и я могу отобразить div ошибки, используя InputFieldError прямо под ним.

Я сопоставляю все ошибки из ответа API с реквизитами, подобными этому:

     function mapStateToProps(state) {
      return { errorMessage: state.errors, countries: state.countries };
    }
  

это означает, что я могу печатать каждую ошибку, с которой я сталкиваюсь в любом месте, подобном этому:

 {this.props.errorMessage
                    ? displayServerErrors(this.props.errorMessage)
                    : null}
  

легко отображать все в одном месте, просто просматривая каждое свойство в ErrorMessage.

Теперь, когда я пытаюсь присвоить ошибки обратно из API ( "errors": {"firstname": []} связано с Field name="firstname" и так далее …), Я не могу найти способ прикрепить ошибку в свойстве «firstname» к правильному компоненту InputFieldError в Field name="firstname"

Я надеюсь, что вопрос достаточно ясен, чтобы суммировать его, я пытаюсь отобразить ошибку, полученную из API, в соответствующий элемент ввода.

Ответ №1:

Попробуйте передать errors.firstname во внутренний компонент поля следующим образом

 <Field name='companyname' type='text' component={<inputField apiErrors={this.props.errorMessage.errors.firstname || null} {...props}/>} className='form-control' validate={validation.required} />
  

и тогда ваше поле ввода будет:

 export const inputField = ({
  input,
  label,
  type,
  className,
  id,
  placeholder,
  meta: { error, touched },
  apiErrors,
  disabled
}) => {
  return (
    <div>
      {label ? (
        <label>
          <strong>{label}</strong>
        </label>
      ) : null}
      <Translate
        {...input}
        type={type}
        color={"white"}
        className={className}
        id={id}
        disabled={disabled}
        component="input"
        attributes={{ placeholder: placeholder }}
      />
      <InputFieldError
        touched={touched}
        error={apiErrors ? apiErrors : <Translate content={error} />}
      />
    </div>
  );
};
  

и:

 class InputFieldError extends Component {
  render() {
    const errors = this.props.error
    let errorContent;
    if (Array.isArray(errors)) {
      errorContent = '<ul>'
      errors.map(error, idx => errorContent = <li key={idx}><Translate content={error}/></li>)
      errorContent  = '</ul>'
    } else {
      errorContent = errors
    }
    return <font color="red">{this.props.touched amp;amp; errorContent}</font>;
  }
}
  

Вы также можете добавить основную ошибку в верхней части вашей формы

 class RegistrationComponent extends  Component {

  onSubmit = (formProps) => {

     this.props.signup(formProps, () => {
       this.props.history.push('/signup/complete');
     });
  };

render() {
    const {handleSubmit} = this.props;
    return (
        <div>
            {this.props.errorMessage.message amp;amp; 
             <Alert>
               <Translate content={this.props.errorMessage.message}/>
             </Alert>
            }
            <form
              className='form-signup'
              onSubmit={handleSubmit(this.onSubmit)}
            >
...
  

Комментарии:

1. Спасибо, это более или менее сработало бы, да, однако это означало бы добавление дополнительной проверки и значения для каждого компонента, apiErrors={(this.props.errorMessageamp;amp; this.props.errorMessage.company_name) || null } поскольку этот проект является временным для меня, я хотел избежать изменения каждого файла.

2. В вашей функции mapsStateToProps вы можете инициализировать пустые реквизиты по умолчанию ErrorMessage, если в хранилище redux есть отметка. Или вы можете сбросить состояние ошибок до значения по умолчанию в store reducer.