如何使用 useContext 钩子传递数据?

时间:2021-01-04 15:25:58

标签: reactjs react-hooks react-context use-context

我正在尝试通过上下文将 petData 传递给 SearchPage 组件。 petData 返回未定义。对我做错的任何帮助。

谢谢

Context.js

import { createContext } from "react";

const PetDataContext = createContext();

export default PetDataContext;

App.js

在 app.js 上,我正在获取数据并将其置于 axios 请求范围之外可访问的状态。然后我试图通过 useContext 钩子传递它。

import PetDataContext from "./Context/context";


function App() {
  const [petData, setPetData] = useState();
  useEffect(() => {
    axios
      .get(`${BACK_PORT}/data`)
      .then(function (response) {
        setPetData(response.data);
      })
  }, []);
  console.log(petData);

  return (
    <div className="App">
      <PetDataContext.Provider value={{ petData }}>
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route path="/" component={MainSignedOut} exact />
            <Route path="/mainsignedin" component={MainSignedIn} />
            <Route path="/searchpage" component={SearchPage} />
            <Route path="/mypets" component={MyPets} />
            <Route path="/admin" component={Admin} />
            <Route exact path="/pets/:id" component={PetPage} />
            <Route component={err404} />
          </Switch>
        </BrowserRouter>
      </PetDataContext.Provider>
    </div>
  );
}

export default App;

SearchPage.jsx

在 Searchpaje 组件上,我试图通过 useContext 传递 petsData,但它返回 undefined。

import PetDataContext from "../../Context/context";


function SearchPage() {
  const { petData } = useContext(PetDataContext);
  console.log("testing123", petData); //returns undefined

  const [filter, setFilter] = React.useState("");

  const filteredData = React.useMemo(() => {
    if (filter == "") return petData;
    return petData.filter(
      (item) =>
        item.name.toLowerCase().includes(filter) ||
        item.breed.toLowerCase().includes(filter)
    );
  }, [petData, filter]);

  return (
    <>
      <SearchBar onSearch={(searchTerm) => setFilter(searchTerm)} />
      <div className="d-flex flex-wrap sp-body">
        <DogCardsDisplayed petData={filteredData} />
      </div>
    </>
  );
}

export default SearchPage;

1 个答案:

答案 0 :(得分:1)

您已使用以下代码行将初始值设置为 undefined

const [petData, setPetData] = useState();

如果这不是你想要的初始值,那么在那里放一些其他的东西,比如一个空数组。

const [petData, setPetData] = useState([])

或者,您可以将其保持为未定义状态,并检查该值是否有可能在您使用它时出现。

  const filteredData = React.useMemo(() => {
    if (!petData) return []; //<--- added this
    if (filter == "") return petData;
    return petData.filter(
      (item) =>
        item.name.toLowerCase().includes(filter) ||
        item.breed.toLowerCase().includes(filter)
    );
  }, [petData, filter]);

P.S:与您的错误无关,但以下可能会导致不需要存在的性能问题:

value={{ petData }}

每次 App 渲染时,都会创建一个新对象。 petData 可能是相同的,但它周围的对象是新的。结果,即使没有任何变化,所有消费者也被迫重新渲染。

如果这是您需要提供的唯一数据,那么您可以删除对象并直接提供数组:

value={petData}

// And change how you consume it to:
const petData = useContext(PetDataContext);

如果您需要一个对象,因为您将提供多种内容,那么请记住该对象,以便仅在其数据更改时重新创建它:

const value = React.useMemo(() => {
  return { petData, somethingElse }
}, [petData, somethingElse]);

// ...

 <PetDataContext.Provider value={value}>