Как мне обновить состояние объекта в реакции через хуки - PullRequest
0 голосов
/ 19 февраля 2020

Это простой вопрос. Как мне успешно обновить объект состояния через реагирующие хуки?

Я только начал использовать ловушки, и мне нравится, как она позволяет использовать простую и чистую функцию JavaScript для создания и управления состоянием с помощью функции useState(), а также вносить изменения, которые влияют на компоненты, используя useEffect() функция, но я не могу заставить работать обновление состояния!

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

enter image description here

Я знаю, что не делаю что-то прямо в коде. Вот мой App компонент, это единственный компонент для извлечения и обновления:

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';


export default function App() {

    // Set date state
    const [data,setData]  = useState({
       data: [],
       loaded: false,
       placeholder: 'Loading' 
    });

    // Fetch and update date
    useEffect(() => {

        fetch('http://localhost:8000/api/lead/')
        .then(response => {
            if (response.status !== 200) {
                SetData({placeholder: 'Something went wrong'});
            }
            response.json()
        })
        .then(result => {
           console.log(data);
           setData({data: result});
        });

    },[]);

    return (
      <h1>{console.log(data)}</h1>
    );
}

ReactDOM.render(<App />, document.getElementById('app'));

Ответы [ 3 ]

2 голосов
/ 19 февраля 2020

В вашем коде 3 ошибки

.then(response => {
            if (response.status !== 200) {
                setData({...data, placeholder: 'Something went wrong'});
            }
            return response.json() // <====== HERE: you need to return the response.json()
        })
.then(result => {
           console.log(data);
           setData({...data, data: result}); // <==== HERE, you need to spread data first
        });
1 голос
/ 20 февраля 2020

Есть несколько вещей, которые вы можете улучшить:

  • useState с реагирующим хуком не ведет себя как аналог класса. Он не объединяет предоставленный объект с состоянием автоматически, вы должны сделать это самостоятельно.
  • Я бы порекомендовал, если вы можете работать без объекта как ваше состояние, так как это может уменьшить количество повторных запросов. рендерится на значительную величину и упрощает последующее изменение формы состояния, так как вы можете просто добавить или удалить переменные и сразу увидеть все случаи использования.

С объектом состояния

export default function App() {

    // Set date state
    const [data,setData]  = useState({
       data: [],
       loaded: false,
       placeholder: 'Loading' 
    });

    // Fetch and update date
    useEffect(() => {
        fetch('http://localhost:8000/api/lead/')
        .then(response => {
            if (response.status !== 200) {
                throw new Error(response.statusText); // Goto catch block
            }
            return response.json(); // <<- Return the JSON Object
        })
        .then(result => {
           console.log(data);
           setData(oldState => ({ ...oldState, data: result})); // <<- Merge previous state with new data
        })
        .catch(error => { // Use .catch() to catch exceptions. Either in the request or any of your .then() blocks
            console.error(error); // Log the error object in the console.
            const errorMessage = 'Something went wrong';
            setData(oldState=> ({ ...oldState, placeholder: errorMessage }));
        });

    },[]);

    return (
      <h1>{console.log(data)}</h1>
    );
}

Без объекта состояния

export default function App() {
    const [data, setData] = useState([]);
    const [loaded, setLoaded] = useState(false);
    const [placeholder, setPlaceholder] = useState('Loading');

    // Fetch and update date
    useEffect(() => {
        fetch('http://localhost:8000/api/lead/')
        .then(response => {
            if (response.status !== 200) {
                throw new Error(response.statusText); // Goto catch block
            }
            return response.json(); // <<- Return the JSON Object
        })
        .then(result => {
           console.log(data);
           setData(data);
        })
        .catch(error => { // Use .catch() to catch exceptions. Either in the request or any of your .then() blocks
            console.error(error); // Log the error object in the console.
            const errorMessage = 'Something went wrong';
            setPlaceholder(errorMessage);
        });

    },[]);

    return (
      <h1>{console.log(data)}</h1>
    );
}
0 голосов
/ 19 февраля 2020

Правильный способ обновить объект с помощью перехватов, чтобы использовать синтаксис функции для обратного вызова setState:

setData(prevState => {...prevState, placeholder: 'Something went wrong'})

Следующий метод переопределит ваше предыдущее состояние объекта:

setData({placeholder: 'Something went wrong'}); // <== incorrect

Ваш финальный код должен выглядеть так:

.then(response => {
    if (response.status !== 200) {
        setData(prevObj => {...prevObj, placeholder: 'Something went wrong'});
    }
    return response.json()
 })
.then(result => {
    setData(prevObj => {...prevObj, data: result});
 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...