Почему useEffect больше не запускает мою загрузку API и не сохраняет результаты в состояние? - PullRequest
1 голос
/ 17 июня 2019

ЦЕЛИ:

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

Я пытаюсь использовать WP-API для использования категорий Wordpress, заголовков публикаций и содержимого публикаций для создания динамического приложения React.

Каждый фрагмент информации играет роль в созданииПриложение React:

  • Категории Wordpress используются для заполнения компонента навигации боковой панели в приложении React.Каждая категория Wordpress будет действовать как элемент в этой навигации.Думайте об этом компоненте как о содержании.

  • Заголовки сообщений будут пунктами подменю для каждой категории.Таким образом, используя в качестве примера рецепты, если одним из пунктов категории в меню был «Мексиканская еда», заголовки постов или пункты подменю могут быть «Тако», «Энчиладас», «Тамалес».

  • Придерживаясь примера мексиканской кухни, содержимое публикации будет отображаться в области основного содержимого в зависимости от того, какой элемент подменю вы щелкнете.Таким образом, если вы нажмете «Tacos» в компоненте меню боковой панели, основное содержимое будет заполнено рецептом «Tacos».Эта основная область содержимого является отдельным компонентом.

ПРОБЛЕМА:

Основная проблема заключается в том, что я могу получить элементы для заполненияна компоненте боковой панели навигации без особых проблем с помощью ловушек React, useEffect и fetch.Однако, как только я нажму на элемент подменю, рецепт не будет заполнен в основной области содержимого.

НАУЧНЫЕ ИССЛЕДОВАНИЯ:

Мне удалось установить, что useEffect isкак-то не устанавливая мое состояние.Я объявляю две переменные, которые обрабатывают данные JSON, которые я получаю, выбирая WP-API.Затем я хочу установить результаты в состояние моего компонента, используя функцию setPost.Однако эта функция setPost не устанавливает состояние.Ниже я приведу примеры кода для ясности.

CODE:

Это мой текущий компонент основного контента, который получает реквизиты.В частности, он получает реквизит «соответствия» от React Router, который содержит URL-адрес для определенного поста WordPress.Я использую это

import React, { useState, useEffect } from 'react'

function MainContent(props) {
    console.log(props)

    useEffect(() => {
        fetchPost()
    }, [])

    const [post, setPost] = useState([])

    const fetchPost = async () => {
        console.log('Fetched Main Content')
        const fetchedPost = await fetch(`http://coolfoodrecipes.xyz/wp-json/wp/v2/posts?slug=${props.match.params.wpslug}`)
        const postContent = await fetchedPost.json()
        console.log(postContent[0])

        setPost(postContent[0])
        console.log(post)
    }

    return (
        <div>
            {/* <h1 dangerouslySetInnerHTML={{__html: post.title.rendered}}></h1> */}
        </div>
    )
}

export default MainContent

Вот результаты 1-го журнала консоли, который содержит содержимое моей проповеди матча:

{
isExact: true,
params: {wpslug: "tacos"},
path: "/:wpslug",
url: "/tacos"
}

Результат моего 3-го журнала консоли, console.log(postContent[0]), приводит к объекту, в котором он возвращает каждый фрагмент детали для этого конкретного сообщения правильно.

После этого я использую setPost(postContent[0]), чтобы сохранить эту информацию в моем состоянии post.

Чтобы подтвердить это, я запускаю console.log(post), которому он возвращает простой [], пустой массив.

РЕЗУЛЬТАТЫ И ОЖИДАНИЯ:

Я ожидал, что содержимое в setPost(postContent[0]) будет должным образом сохранено в состоянии post, чтобы я мог использовать его для отображения содержимого на странице.

Однако фактический результат заключается в том, чтов состояние ничего не сохраняется, и каждый раз, когда я нажимаю на другие категории, такие как «Тамалес» или «Энчиладас», URL-адрес ОБНОВЛЯЕТСЯ обновлением, но он никогда не извлекает информацию после первого извлечения.

Iзнаю, что это длинный вопрос, но любой, кто мог бы помочь этому бедному новичку, был бы абсолютным спасителем!Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 17 июня 2019

Возможно попробуйте изменить const postContent = await fetchedPost.json() на const postContent = await fetchedPost.data

0 голосов
/ 17 июня 2019

Сначала давайте посмотрим на вашу вторую проблему / ожидание: она никогда не извлекает информацию после первой выборки.

Функция useEffect может иметь два параметра. Функция обратного вызова и массив зависимостей. Функция эффекта будет вызываться только при изменении одной из ее зависимостей. Если второй параметр не указан, функция будет выполняться при каждом повторном рендеринге. Ваш массив пуст; это означает, что эффект будет запущен при первом монтировании компонента, после чего он не будет перезапущен.

Чтобы решить эту проблему, вам нужно правильно добавить свои зависимости. В вашем случае вы хотите повторно извлечь, если props.match.params.wpslug изменится.

useEffect(() => {
        fetchPost()
}, [props.match.params.wpslug])

Теперь о проблеме, по-видимому, неправильной установки состояния. Кажется, нет ничего плохого в настройке / обновлении состояния в вашем примере. Проблема в том, что переменная 'post' для текущего цикла рендеринга уже установлена ​​на [] и не изменится до следующего цикла (вы должны были пометить его как const, чтобы он не мог изменить его значение).

Я попытаюсь объяснить 2 цикла здесь.

/* First run, should be the mounting of the component */
function MainContent(props) {
    const slug = props.match.params.wpslug;
    const [post, setPost] = useState([]) // 1. post is currently []

    useEffect(() => { // 3. the useEffect callback will be called, i.e. fetching posts
        fetchPost()
    }, [slug])

    const fetchPost = async () => {
        const fetchedPost = await fetch(`http://coolfoodrecipes.xyz/wp-json/wp/v2/posts?slug=${slug}`)
        const postContent = await fetchedPost.json()

        // 4. you change the state of this component, 
        // React will run the next render-cycle of this component
        setPost(postContent[0]) 
    }

    return (
        <div>
            <h1>{post.title}</h1> {/* 2. React will tell the browser to render this */}
        </div>
    )
}
/* Second run, initiated by setting the post state */
function MainContent(props) {
    const slug = props.match.params.wpslug;
    const [post, setPost] = useState([]) // 1. post is now [{title: 'TestPost'}]

    useEffect(() => { // on this cycle this useEffect callback will not run because 'slug' did not change
        fetchPost()
    }, [slug])

    const fetchPost = async () => {
        const fetchedPost = await fetch(`http://coolfoodrecipes.xyz/wp-json/wp/v2/posts?slug=${slug}`)
        const postContent = await fetchedPost.json()

        setPost(postContent[0]) 
    }

    return (
        <div>
            <h1>{post[0].title}</h1> {/* 2. React will tell the browser to render this */}
        </div>
    )
}

Здесь (https://overreacted.io/a-complete-guide-to-useeffect/) - очень интересная статья о новом хуке useEffect и о некоторых проблемах, с которыми вы столкнулись.

0 голосов
/ 17 июня 2019

setPost также асинхронный, как и обычный setState класса Component.Поэтому вы должны использовать

await setPost(postContent[0])
console.log(post)

, чтобы получить результат внутри вашей функции

...