Не удается получить доступ к свойству объекта, хотя оно должно быть там

#javascript #reactjs

Вопрос:

У меня есть компонент в react, который извлекает историю, написанную пользователем из бэкенда. Затем я сохраняю json в storyState , и когда я регистрирую его, там находятся необходимые свойства, такие как «заголовок», но когда я пытаюсь получить доступ к названию свойства, я получаю эту ошибку:

 TypeError: Cannot read properties of undefined (reading 'title')
 

Вот код:

 import { useState, useEffect } from 'react';
import styled from 'styled-components';

export const StoryPage = () => {
    const [storyState, setStoryState] = useState({
        story: {},
        isLoaded: false,
        error: null,
    });

    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    const id = urlParams.get('storyid');

    useEffect(() => {
        fetch('http://localhost:5000//getstory?storyid='   id)
            .then((response) => {
                console.log('response is', response);
                if (response.status !== '200') {
                    let err = Error;
                    err.message = 'Invalid response code: '   response.status;
                    setStoryState({ error: err });
                }
                return response.json();
            })
            .then((json) => {
                console.log('json is', json);
                setStoryState({
                    story: json.story,
                    isLoaded: true,
                });
            });
    }, []);

    console.log('storystate.story', storyState.story);

    return (
        <>
            <h1>test</h1>
            <h1>{storyState.story.title}</h1>
        </>
    );
};

export default StoryPage;
 

Я проверил StackOverflow и попробовал использовать JSON.parse , но, к сожалению, это не сработало.

Когда я это делаю < h1 >{storyState.story}</ h1 > , я получаю весь объект в строковой форме со всеми свойствами, как и ожидалось.

Вот моя консоль:

введите описание изображения здесь

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

1. При первом рендеринге он еще недоступен , поэтому вы помещаете загрузчик или рендеринг null, а затем после того, как он будет доступен, показываете данные, которые вы пытаетесь отобразить …. Просто if(!data)return null;return(whaterver u want next ); чтобы понять это, попробуйте зарегистрировать storyState.story внутри return ….

Ответ №1:

Проблема в этой строке —

 if (response.status !== "200") {
}
 

Это должно быть 200 вместо «200». Вы можете проверить console.log("response is", response); , что это число 200, а не строка.

Примечание: Всегда используйте приведенную ниже конструкцию для задания состояния объектов —

 { ...previousState, { newkey: newvalue } }
 

Вышесказанное использует предыдущие значения объекта и заменяет их новыми значениями.

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

1. Большое вам спасибо, это сработало для меня! С этого момента я буду использовать эту конструкцию для задания состояния!

Ответ №2:

При самом первом рендеринге данные недоступны, следовательно, вы должны выполнять рендеринг <h1>{storyState.story.title}</h1> только тогда, когда данные получены и доступны, поэтому добавьте оператор if в рендеринг или вы также можете использовать дополнительную цепочку

   <h1>{storyState?.story?.title}</h1>
 

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

1. Спасибо и тебе, Тарун, твой ответ действительно сработал!

Ответ №3:

Может возникнуть задержка при извлечении данных с сервера, вы можете добавить в него загрузчик, который проверяет, есть ли значение storySTate , а затем визуализирует данные, или добавить другую функцию useEffect, которая регистрирует файл всякий раз, когда происходит изменение в цепочке storyState, например:

  useEffect(() => {   
        console.log(storyState.story)
    }, [storyState])