如何在上下文 API 中传递路由参数



我正在使用上下文API,我的上下文文件中有这个:

useEffect(() => {
async function getSingleCountryData() {
const result = await axios(
`https://restcountries.eu/rest/v2/alpha/${props.match.alpha3Code.toLowerCase()}`
);
console.log(result)
setCountry(result.data);
}
if (props.match) getSingleCountryData();
}, [props.match]);

在我使用的组件中,它不起作用,因为它不知道 props.match.alpha3Code 是什么。如何传递值?alpha3Code 来自 URL:localhost:3000/country/asaalpha3Codeasa在哪里,我如何获取此值?

基本上,我想做的是。我在主页上列出了国家/地区列表。现在我正在尝试获取有关单个国家/地区的更多信息。路由/country/:alpha3Code从 API 获取alpha3Code的位置。

FWIW,这是我的完整上下文文件:

import React, { useState, createContext, useEffect } from 'react';
import axios from 'axios';
export const CountryContext = createContext();
export default function CountryContextProvider(props) {
const [countries, setCountries] = useState([]);
const [country, setCountry] = useState([]);
useEffect(() => {
const getCountryData = async () => {
const result = await axios.get(
'https://cors-anywhere.herokuapp.com/https://restcountries.eu/rest/v2/all'
);
setCountries(result.data);
};
getCountryData();
}, []);
useEffect(() => {
async function getSingleCountryData() {
const result = await axios(
`https://restcountries.eu/rest/v2/alpha/${props.match.alpha3Code.toLowerCase()}`
);
console.log(result)
setCountry(result.data);
}
if (props.match) getSingleCountryData();
}, [props.match]);
return (
<CountryContext.Provider value={{ countries, country }}>
{props.children}
</CountryContext.Provider>
);
}

在我正在使用的组件中country,我有:const { country } = useContext(CountryContext);

我知道我可以从组件本身做到这一点,但我正在学习如何使用上下文 API,所以我正在处理上下文中的所有 API 调用。

我正在使用的 API 在这里

代码沙盒链接

项目Github链接

您可以通过传递更新上下文状态的 setter 函数来从使用它的组件更新上下文。

export default function CountryContextProvider({ children }) {
const [countries, setCountries] = useState([]);
const [country, setCountry] = useState([]);
const [path, setPath] = useState('');
useEffect(() => {
async function getSingleCountryData() {
const result = await axios(`your/request/for/${path}`);
setCountry(result.data);
}
if(path) getSingleCountryData();
}, [path]);
return (
<CountryContext.Provider value={{ countries, country, setPath }}>
{children}
</CountryContext.Provider>
);
}

现在,挂载此组件后,使用setPath使用路由匹配项更新请求终结点。

const Details = ({ match }) => {
const {
params: { alpha3Code }
} = match;
const { country, setPath } = useContext(CountryContext);
useEffect(() => {
setPath(alpha3Code);
}, [alpha3Code]);
return (
<main>Some JSX here</main>
);
};
export default withRouter(Details);

链接是一个有效的代码沙箱实现

在我使用的组件中,它不起作用,因为它不知道 props.match.alpha3Code是什么。如何传递值?这 alpha3Code 来自网址:localhost:3000/country/asa where asa 是 alpha3Code,我怎样才能得到这个值

我想你问题的根源就是这个。您不知道aplha3Code参数来自哪个。我已经深入研究了您的 GitHub 存储库以使其更清晰。

  1. 首先,match是 react-router 提供的条款之一。当你使用类似props.match, props.history, props.location的东西时,你必须用withRouter包裹你的组件,这是react-router提供的高阶组件。在路由器上查看。例如,下面是 react-router 提供的withRouter用法:
// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
render() {
const { match, location, history } = this.props;
return <div>You are now at {location.pathname}</div>;
}
}
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

ShowTheLocationwithRouterHOC包裹,它将传递所有路线道具(比赛,历史记录,位置等)通过道具ShowTheLocation。然后在ShowTheLocation中,您可以使用类似props.match.够清楚吗?

所以回到你的问题!您还没有通过withRouter包装任何组件,是吗?坚持下去,玩得开心!你很快就会弄清楚的!

另外,请注意,您必须将组件放在BrowserRouter下才能使用反应路由器的东西

  1. 如果你想使用 Hooks,请看一下这个超级有用的:

    https://usehooks.com/useRouter/

它将所有useParams, useLocation, useHistory, and use useRouteMatch连接包装到一个useRouter中,仅公开我们需要的数据和方法。然后,例如,在组件内部,执行以下操作:

import { useRouter } from "./myCustomHooks";
const ShowMeTheCode = () => { 
const router = useRouter();
return <div>This is my alpha3Code: {router.math.params.alpha3Code}</div>;
}

更新 1 来自 Peoray 的回复:

这是出现问题的地方: https://github.com/peoray/where-in-the-world/blob/cb09871fefb2f58f5cf0a4f1db3db2cc5227dfbe/src/pages/Details.js#L6

你应该避免像这样直截了当地打电话给useContext()。看看我下面的例子:

// CountryContext.js
import { useContext, createContext } from "react";
const CountryContext = createContext();
export const useCountryContext = () => useContext(CountryContext);

相反,您应该通过自定义钩子包装它,如上useCountryContext。然后,在Details组件中,导入它并执行以下操作:

import React, from 'react';
import { useCountryContext } from '../contexts/CountryContext';
const Details = (props) => {
const { country } = useCountryContext();
...
}

更新 2 来自 Peorey 的回复:

虽然我已经提前为你说了,但我只是觉得你没有付出足够的努力来完成我说的话。

另外,请注意,您必须将组件放在BrowserRouter能够使用反应路由器的东西

在代码沙盒中,它显示Cannot read property 'match' of undefined错误。好的,正如我上面所说,您没有将ContextCountryProvider移动到BrowserRouter下以获得useRouter工作。

我已经为您修复了它,并且屏幕弹出了,请在此处更新的代码sanbox中查看它。您将在App.js文件中获得所需的内容。

虽然它仍然在那里抛出一些 Axios 错误,但我认为我的工作已经完成。剩下的就看你了。

您可以使用useParams钩子在上下文提供程序中获取所需的所有内容。文档

像这样:

  1. 在提供程序组件所在的文件中导入useParams
  2. 在您的CountryContextProvider组件顶部添加以下内容:
const { alpha3Code } = useParams();
  1. 更新需要props.matchuseEffect
useEffect(() => {
async function getSingleCountryData() {
const result = await axios(
`https://restcountries.eu/rest/v2/alpha/${alpha3Code.toLowerCase()}`
);
console.log(result)
setCountry(result.data);
}
if (alpha3Code) getSingleCountryData(); // or if you need `match` - do not destructure useParams()
}, [alpha3Code]);

相关内容

  • 没有找到相关文章

最新更新