通过子组件为React上下文增值

时间:2019-07-14 12:39:16

标签: javascript reactjs react-native axios react-context

我试图在我的React Native应用程序中使用React上下文作为状态管理器。

这里是上下文:

import React, { createContext, useState, useEffect } from "react";
import axios from "axios";
export const GlobalContext = createContext();

export const Provider = ({ children }) => {
  const [tracksList, setTracksList] = useState([
    {
      track_list: []
    }
  ]);

  useEffect(() => {
    axios
      .get(
        `https://cors-anywhere.herokuapp.com/https://api.musixmatch.com/ws/1.1/chart.tracks.get?page=1&page_size=10&country=us&f_has_lyrics=1&apikey=${
          process.env.REACT_APP_MM_KEY
        }`
      )
      .then(res => {
        setTracksList([
          {
            track_list: res.data.message.body.track_list
          }
        ]);
      })
      .catch(err => console.log(err));
  }, []);

  return (
    <GlobalContext.Provider value={[tracksList, setTracksList]}>
      {children}
    </GlobalContext.Provider>
  );
};

export const Consumer = GlobalContext.Consumer;

子组件。在这里,我想进行API调用以获取用户并将此用户字段设置为全局上下文。我可以从消费者那里获得上下文值,但是如何设置新值呢?

import React, { useContext } from "react";

import { GlobalContext } from "../../context/context";

const Demo = () => {
  const contextValue = useContext(GlobalContext);

  console.log(contextValue, "Context outside from JSX");
  return <div>Content</div>;
};

export default Demo;

那么,是否有可能像Redux一样从每个子组件向React上下文添加新值?预先感谢!

1 个答案:

答案 0 :(得分:1)

您可以使用useReducer效果来实现Redux reducer:

// Create context
export const ApiContext = React.createContext();

// Create some reducer function
const reducer = (state, action) => {
  if (action.type === 'some action name') {
    return {
      ...state,
      report: action.payload,
    };
  }

  return state;
};

// Overwrite a context provider
const Provider = ({ children }) => {
  const [state, dispatch] = React.useReducer(reducer, {});

  return (
    <ApiContext.Provider
      value={{
        ...state,
        dispatch,
      }}
    >
      {children}
    </ApiContext.Provider>
  );
};

然后您可以在组件中使用以下内容:

const Component = () => {
  const { dispatch, report } = React.useContext(ApiContext);

  React.useEffect(() => {
    const asyncPost = async () => {
      const response = await fetch('some endpoint', {
        method: 'POST',
      });

      const payload = await response.json();

      // This will call a reducer action and update a state
      dispatch({
        type: 'some action name',
        payload,
      });
    }
  }, []);

  ...
};

因此,在安装Component时,状态将为空对象。然后,当您使用some action name操作更新状态时,该状态将变为{ report: some data from fetch }