Вернуть объект внутри useEffect () и получить доступ к нему снаружи в React (после присвоения состояния) - PullRequest
0 голосов
/ 18 июня 2020

TLTR:

const ReturnPagination = () => {
    const [header, setHeader] = useState(null);
    useEffect(() => {

        let pageinitial = 1;
        fetch(config.taskRoute + '?page=' + pageinitial)
        .then(response => {

            var myvar = {
                res: response.json(),
                headers: response.headers.get('x-wp-totalPages')
            }
            console.log(myvar.headers);
            //will print the value that I need, in this case a number
            return lello;
        } )
        .then(setHeader)

        .catch(console.error)

    }, []);
    console.log(header.headers);
    //will display an error on the console

    if (header) {
        return (
            <Fragment>


            </Fragment>
            );

    } else {
        return null;
    }
}

Таким образом, в react можно получить доступ к переменной и ее подуровню (res / headers) внутри функции useEffect (), но невозможно получить доступ к ней вне ее.

Однако возможно получить доступ ко всей переменной вне функции useEffect сразу после pu sh состояния в это, но если я попытаюсь получить доступ к подуровню (например, header.headers), консоль будет напечатайте следующую ошибку:

TypeError: Cannot read property 'res' of null

Почему моя переменная равна нулю? Это ошибка?

Проблема:

Вот мой компонент:

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

const Fragment = React.Fragment;

const rootURL = 'mywordpress';

const config = {
    rootURL: rootURL,
    taskRoute: `${rootURL}/wp-json/wp/v2/posts`,
};

const ReturnWordpress = () => {
    const [data, setData] = useState(null);
    const [header, setHeader] = useState(null);
    useEffect(() => {
        fetch(config.taskRoute)
        .then(response => {
            return response.json()
        } )
        .then(setData)
        .catch(console.error)
        fetch(config.taskRoute)
        .then(res => {
            return res.headers.get('x-wp-total')
        } )
        .then(setHeader)

    }, []);
    //console.log(data, header);
    if (data) {
        return (
            <Fragment>
            {data.map((content, i) => {
                return(
                    <div className='col-md-6' key={i}>
                    <h1>{content.title.rendered}</h1>
                    <div
                    dangerouslySetInnerHTML={{
                        __html: content.excerpt.rendered
                    }}></div>
                    <h4><a href={content.link}>Read more</a></h4>
                    </div>
                    );
            })}
            </Fragment>
            );

    } else {
        return null;
    }

}

export default ReturnWordpress;

И вот моя проблема. Идея состоит в том, чтобы извлечь объект из вызова выборки в реакции. Этот код работает нормально, но использует два вызова выборки. Я хотел бы использовать только один вызов fetch и извлечь объект из этого вызова следующим образом:

useEffect(() => {
    fetch(config.taskRoute)
    .then(response => {
        return {
            res: response.json(),
            headers: res.headers.get('x-wp-total')
        } 
    } )
    .then(setData)
    .catch(console.error)
}, []);
console.log(data);

Этот фрагмент также будет работать нормально, пока я не попытаюсь получить доступ к объекту, например таким образом = data.res. На самом деле я даже не уверен, что это объект, но в любом случае, если я попытаюсь получить к нему доступ как к массиву (data [res]), это тоже не сработает.

Допустим, я буду попробуйте l oop, хотя объект, прежде чем я визуализирую его в компоненте, примерно так:

for (const property in data) {
    console.log(`${property}: ${data[property]}`);
}

Я все равно не смогу получить доступ к свойству res объекта, потому что он вернет res: [object Promise].

Еще одна проблема, с которой я столкнулся с реакцией, заключается в том, что очень сложно отладить такой фрагмент кода, потому что консоль не будет указывать на ошибку, и я даже не могу консоль зарегистрируйте некоторый уровень объекта, потому что что-то вроде data.header или data.res заставит его сломать мой стек.

Я почти уверен, что решение очень простое, но на данный момент у меня нет Подскажите, как я могу решить загадку. Есть подсказка?

1 Ответ

1 голос
/ 18 июня 2020

Возможно, вы сможете использовать Jquery $ .when (https://api.jquery.com/jquery.when/)

Другой способ сделать это - использовать Promise.all ()


const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

Тогда, чтобы использовать это обещание

create a function with the promise

async function example(){
return Promise.all([...]).then(function(values){
resolve(whatever)
})
})


function mainFunction(){
const responseValue = await example();
console.log("Do something with response value");

}



}

Я не уверен на 100%, что у меня правильный синтаксис, но я думаю, что это то, что вы ищете. Просто выполните поиск в Google javascript, дождитесь и используйте функции asyn c, так как для выполнения обещания требуется время

...