Реагирует на контекстный API, возвращающий неопределенное значение при установке состояния - PullRequest
0 голосов
/ 05 февраля 2020

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

Здесь, в MyProvider. js файле, я определяю своего провайдера и его просто хранит 2 массива json obj

import {MyContext} from "./MyContext";
import React, {useState} from "react";

export const MyProvider = (props) => {
    const intialState = {
        featuredListings: [],
        setFeaturedListings: (val) => setState({...state, featuredListings: val}),
        featuredVendors: [],
        setFeaturedVendors: (val) => setState({...state, featuredVendors: val})
    }

    const [state, setState] = useState(intialState)

    return (
        <MyContext.Provider
            value={state}
        >
            {props.children}
        </MyContext.Provider>
    );
}

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

<MyProvider>
    <div className="content">
        <Header/>
        <Router>
            <Home path="/"/>
        </Router>
    </div>
    <Footer />
</MyProvider>

В моем файле Home. js я выполняю сетевой вызов в хуке useEffect, который успешно возвращает ожидаемый json и с этим json ответ я обновляю состояние контекста, чтобы его можно было видеть глобально.

Мой код для этого

export const Home = () => {
    let state = useContext(MyContext)

    async function apiCalls() {
        const featuredVendors = await getFeaturedVendors()
        console.log("featuredVendors - ", featuredVendors) // the correct response is returned
        state.setFeaturedVendors(featuredVendors)

        const featuredListings = await getFeaturedListing()
        console.log("featuredListings - ", featuredListings) // the correct response is returned
        state.setFeaturedListings(featuredListings)
    }

    useEffect(() => {
        apiCalls()
    }, []);

    return (
        <div>
            {console.log(state.featuredVendors)}  // empty array
            {console.log(state.featuredListings)} // contains correct values
        </div>
    )
}

]

Чтобы удалить любую неопределенность моего контекста создается в отдельном файле, который называется MyContext. js, и я создаю контекст следующим образом:

export const MyContext = React.createContext()

Почему state.featuredVendors не обновляется когда я его установлю?

Также еще одна странная вещь, которую я заметил, это если я переставлю порядок вызовов, то есть сначала вызов getFeaturedListing , за которым следуют getFeaturedVendors , тогда мои обновления состояния только для featuredVendors и featuredListings будут пустым массивом.

1 Ответ

1 голос
/ 05 февраля 2020

При вызове useState initialValue устанавливается только один раз. Когда ваш MyProvider монтируется впервые, состояние инициализируется вашими методами setFeaturedListings и setFeaturedVendors, но они не обновляются при изменении значения state. Поэтому значение state при распространении значений всегда будет его начальным значением.

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

    const intialState = {
        featuredListings: [],
        setFeaturedListings: (val) => setState(state => ({...state, featuredListings: val})),
        featuredVendors: [],
        setFeaturedVendors: (val) => setState(state => ({...state, featuredVendors: val}))
    }

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

export const MyProvider = (props) => {
  const intialState = {
      featuredListings: [],
      featuredVendors: [],
  }
  const [state, setState] = useState(intialState)
  return (
      <MyContext.Provider
          value={{
            ...state,
            setFeaturedListings: (val) => setState({...state, featuredListings: val}),
            setFeaturedVendors: (val) => setState({...state, featuredVendors: val})
          }}
      >
          {props.children}
      </MyContext.Provider>
  );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...