реагировать. js как отображать несколько сообщений об ошибках - PullRequest
0 голосов
/ 11 апреля 2020

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

Мои намерения создать компонент регистрации, где бэкэнд возвращает ошибки проверки в случае, если есть какие-либо объекты в форме, имеющие следующую структуру.

{
    "username": [
        "A user with that username already exists."
    ],
    "email": [
        "A user is already registered with this e-mail address."
    ]
}

Менеджер состояний, который я выбрал для использования, - redux , так что это возвращается каждый раз, когда отправляется функция register.

Так как она имеет эту структуру, я написал функцию, которая поможет мне разобрать ее и получать только о фактических ошибках (строках).

    const walkNestedObject = (obj, fn) => {
        const values = Object.values(obj)

        values.forEach(val =>
            val && typeof val === "object" ? walkNestedObject(val, fn) : fn(val))
    }

Теперь я хочу отобразить их в представлении, поэтому я написал другую функцию, которая должна это делать

    const writeError = (value) => {
        return <Alert message={value} type="error" showIcon />
    }

Внизу, в фактическом компоненте, который я называю так :

{(props.error) ? walkNestedObject(props.error, writeError) : null}

К моему удивлению, если я console.log возвращаемое выше значение в writeError, оно работает безупречно, печатается каждая отдельная ошибка, но ни одна из них не отображается.

To отладка этого я пробовал несколько вариантов, и ни один из них, похоже, не работал, я даже назвал writeError функцию в компоненте как

{writeError('test')} 

, и она работала по какой-то причине.

На этом этапе я просто предполагаю, что для выполнения этой задачи требуются знания о реакции, о которых я только сейчас знаю.

РЕДАКТИРОВАТЬ: ложный пример можно найти более здесь Кроме того, я попытался использовать первые два ответа и при отображении ошибок я получаю это

Unhandled Rejection (TypeError): props.error.map is not a function

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

export const authSignup = (username, email, password1, password2) => dispatch => {
    dispatch(authStart());
    axios.post('http://127.0.0.1:8000/rest-auth/registration/', {
        username: username,
        email: email,
        password1: password1,
        password2: password2
    })
        .then(res => {
            const token = res.data.key;
            const expirationDate = new Date(new Date().getTime() + 3600 * 1000);
            localStorage.setItem('token', token);
            localStorage.setItem('expirationDate', expirationDate);
            dispatch(authSuccess(token));
            dispatch(checkAuthTimeout(3600));
        })
        .catch(err => {
            dispatch(authFail(err.response.data))
        })
}

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

Подумайте об изменении топологии сообщений об ошибках:

"errors": [
  { "type": "username", "message": "Username already in use." },
  { "type": "email", "message": "Email address already in use."}
]

Это немного упростит вашу реализацию:

// MyLogin.jsx
import React from 'react'

const MyLogin = () => {
  /**
   * Here we're using state hooks, since it's much simpler than using Redux.
   * Since we don't need this data to be made globally available in our
   * application, it doesn't make sense to use Redux anyway.
   */
  const [errors, setErrors] = React.useState([])

  const handleLogin = (event) => {
    event.preventDefault()
    axios.post('/api/login', formData).then(() => successAction(), (error: any) => {
      setErrors(error) // Update our local state with the server errors
    })
  }

  return (
    <>
      {errors.length && ( // Conditionally render our errors
        errors.map((error) => (
          <Alert type={error.type} message={error.message} />
        )
      )}
      <form onSubmit={handleLogin}>
        <input type='text' name='email' />
        <input type='text' name='username' />
        <input type='password' name='password' />
      </form>
    <>
  )
}

export default MyLogin
0 голосов
/ 11 апреля 2020

Ваша функция walkNestedFunction проверяет каждый слой объекта, и, если данный слой объекта является самим объектом, она затем использует этот объект для запуска вашей функции - в данном случае это writeError. writeError возвращает ошибку <Alert />, как только возникает ошибка. Но когда вы вставляете writeError в круговую логику c из walkNestedFunction, она попадет в первый оператор return, отобразит его на странице, а затем остановит рендеринг. Я думаю, именно поэтому вы получаете полный список ошибок, записанных на консоли. Ваш walkNestedFunction продолжает вращаться вниз по слоям объекта, пока это не будет сделано. Но в React будет отображаться только первый оператор return.

Лучшей тактикой c было бы изменение функции writeError для записи ошибок в переменную состояния. Затем вы можете отобразить эту переменную состояния. Каждый раз, когда состояние обновляется, компонент будет перерисовываться с обновленным состоянием.

// Define state in your component to contain an array of errors:

state = {
  errors: []
}

// Add an error into state with each iteration of writeError

const writeError = (error) => {
  this.setState({
    errors: [
      ...this.state.errors,
      error
    ]
  })
}


// inside render(), render the state variable containing your errors

<div>
  { this.state.errors.map(error => <p>error</p>) }
</div>

`

...