如何结合自定义钩子来获取数据和上下文?

IT技术 reactjs
2021-04-28 21:55:21

我有一个自定义钩子来获取表单提交上的数据

export const getIssues = ({ user, repo }) => {
  const [issues, setIssues] = useState([]);

  const handleInputChange = (e) => {
    e.preventDefault();
    axios.get(`https://api.github.com/repos/${user}/${repo}/issues`)
      .then((response) => {
        setIssues(response.data);
      })
      .catch((err) => console.log(err));
  };

  return {
    issues,
    onSubmit: handleInputChange,
  };
};

在我的组件中,我这样称呼它

const response = getIssues({ user: user.value, repo: repo.value })
  return (
    <form className={css['search-form']} {...response}>...</form>
)

问题是我想issues从另一个组件的钩子中获取我的值。为此,我想使用 Context。但我不知道该怎么做。

我可以调用这个函数并将它传递给Provider,但我不能在没有参数的情况下调用它。所以我有点卡住了。

所有的帮助将不胜感激。

2个回答

你说你需要React.Context处理这种情况是对的。

  1. 您需要将组件包装到此上下文中。
import React from "react";

const IssuesStateContext = React.createContext();
const IssuesDispatchContext = React.createContext();

function issuesReducer(state, action) {
  switch (action.type) {
    case "setIssues": {
      return [...action.payload];
    }

    default: {
      throw new Error(`Unhandled action type: ${action.type}`);
    }
  }
}

function IssuesProvider({ children }) {
  const [state, dispatch] = React.useReducer(issuesReducer, []);
  return (
    <IssuesStateContext.Provider value={state}>
      <IssuesDispatchContext.Provider value={dispatch}>
        {children}
      </IssuesDispatchContext.Provider>
    </IssuesStateContext.Provider>
  );
}

function useIssuesState() {
  const context = React.useContext(IssuesStateContext);
  if (context === undefined) {
    throw new Error("useIssuesState must be used within a IssuesProvider");
  }
  return context;
}
function useIssuesDispatch() {
  const context = React.useContext(IssuesDispatchContext);
  if (context === undefined) {
    throw new Error("useIssuesDispatch must be used within a IssuesProvider");
  }
  return context;
}

export { IssuesProvider, useIssuesState, useIssuesDispatch };

通过在上下文中使用这种分离,您将能够在一个组件中设置来自 github 的问题,并在一个完全不同的组件中呈现它们。

例子:

应用程序.js

ReactDOM.render(
  <IssuesProvider>
    <Component1 />
    <Component2 />
  </IssuesProvider>
)

组件 1

import React from 'react'
import { useIssuesDispatch } from './issues-context'

function Component1() {
  const dispatch = useIssuesDispatch()
  // fetch issues
  // .then dispatch({ type: 'setIssues', payload: response })

  // render
}

组件 2

import React from 'react'
import { useIssuesState } from './issues-context'

function Component2() {
  const issues = useIssuesState()

  // if issues.length > 0 ? render : null
}

您可以编写一个 Issues 上下文提供程序,该提供程序将提供{issues,useIssues}问题所在的位置,而 useIssues 是一个需要{user,repo}.

export const Issues = React.createContext();
export default ({ children }) => {
  const [issues, setIssues] = useState([]);
  const useIssues = ({ user, repo }) => {
    useEffect(() => {
      axios
        .get(
          `https://api.github.com/repos/${user}/${repo}/issues`
        )
        .then(response => {
          setIssues(response.data);
        })
        .catch(err => console.log(err));
    }, [user, repo]);
    return issues;
  };
  return (
    <Issues.Provider value={{ issues, useIssues }}>
      {children}
    </Issues.Provider>
  );
};

拥有所有需要问题的组件的组件可以导入这个问题提供者:

import IssuesProvider from './IssuesProvider';
export default () => (
  <IssuesProvider>
    <ComponentThatNeedsIssues />
    <ComponentThatSetsAndGetsIssues />
  </IssuesProvider>
);

对于需要设置问题的组件,您可以从上下文中获取 useIssues:

const { useIssues } = useContext(Issues);
const issues = useIssues({user,repo});

对于只需要问题的组件:

const { issues } = useContext(Issues);

看到这一切一起工作有一个codepen这里