Javascript React使用React挂钩从路由器获取道具
我正在尝试使用Javascript React使用React挂钩从路由器获取道具,javascript,reactjs,react-router,react-hooks,Javascript,Reactjs,React Router,React Hooks,我正在尝试使用React Hooks重构我的代码,我真的不明白如何通过React路由器使用Hooks将道具传递给我的组件 旧的(正常)React代码如下所示: App.js import React from 'react'; import { withRouter } from "react-router-dom"; import {Routes} from './routes/Routes'; function App() { const childProps={something
React Hooks
重构我的代码,我真的不明白如何通过React路由器使用Hooks将道具传递给我的组件
旧的(正常)React代码如下所示:
App.js
import React from 'react';
import { withRouter } from "react-router-dom";
import {Routes} from './routes/Routes';
function App() {
const childProps={something: "else"};
return (
<div className="App">
<Routes childProps={childProps} />
</div>
);
}
export default withRouter(App);
从“React”导入React;
从“react router dom”导入{withRouter};
从“./Routes/Routes”导入{Routes};
函数App(){
const childProps={something:“else”};
返回(
);
}
使用路由器(App)导出默认值;
Routes.js
import {Switch, Route} from 'react-router-dom';
import Game from '../game/Game';
import Scenario from '../game/Scenario';
const CustomRoute = ({ component: C, props: cProps, ...rest }) =>
<Route
{...rest}
render={(props) =>
<C {...props} {...cProps} />
}
/>;
export const Routes = ({childProps}) =>
<Switch>
<Route path="/" exact component={Game} props={childProps} />
<CustomRoute path="/scenario/:id" exact component={Scenario} props={childProps}/>
</Switch>
从'react router dom'导入{Switch,Route};
从“../Game/Game”导入游戏;
从“../game/Scenario”导入场景;
const CustomRoute=({component:C,props:cProps,…rest})=>
}
/>;
导出常量路由=({childProps})=>
Game.js
import React from 'react';
const Game = () => {
return (
<div className="Game">
<header className="Game-header">
<a href="/scenario/0">
START
</a>
</header>
</div>
);
};
export default Game;
从“React”导入React;
康斯特游戏=()=>{
返回(
);
};
出口违约博弈;
Scenario.js
export default class Scenario extends Component {
constructor(props) {
super(props);
this.state = {
scenarios: null,
scenarioId: null,
currentScenario: null
}
}
async componentDidMount() {
const scenarioId = await this.props.match.params.id;
const scenarios = await data.scenarios;
this.setState({scenarios, scenarioId});
this.getScenario();
}
getScenario = () => {
this.state.scenarios.forEach((scenario) => {
if (scenario.id === this.state.scenarioId) {
const currentScenario = scenario;
this.setState({currentScenario});
}
})
}
render() {
return (
<div>
{this.state.currentScenario != null
? this.state.currentScenario.options.length === 1
? (
<div>
<div>{this.state.currentScenario.text}</div>
<div>{this.state.currentScenario.options[0].text}</div>
<a href="/">Go Back</a>
</div>
)
: (
<div>
<div>{this.state.currentScenario.text}</div>
<div>{this.state.currentScenario.options.map((option, index) => (
<div key={index}>
<a href={`/scenario/${option.to}`}>
{option.text}
</a>
</div>
))}</div>
</div>
)
: null
}
</div>
);
}
};
import React, { Component, useState, useEffect } from 'react';
import data from '../data/fake';
import {useRouter} from '../routes/HookRouter';
const RouterContext = React.createContext(null);
const HookSceneario = () => {
const [scenarios, setScenarios] = useState(null);
const [scenarioId, setScenarioId] = useState(null);
const [currentScenario, setCurrentScenario] = useState(null);
// Similar to componentDidMount and componentDidUpdate:
// Update the document title using the browser API
// console.log(React.useContext(RouterContext));
useEffect(() => {
console.log(scenarios);
});
return (
<div>
// ...
</div>
);
}
导出默认类场景扩展组件{
建造师(道具){
超级(道具);
此.state={
场景:空,
scenarioId:null,
当前场景:空
}
}
异步组件didmount(){
const scenarioId=等待this.props.match.params.id;
const scenarios=wait data.scenarios;
this.setState({scenarioId,scenarioId});
这个.getScenario();
}
getScenario=()=>{
this.state.scenarios.forEach((scenario)=>{
if(scenario.id==this.state.scenarioId){
const current scenario=scenario;
this.setState({currentScenario});
}
})
}
render(){
返回(
{this.state.currentScenario!=null
?this.state.currentScenario.options.length==1
? (
{this.state.currentScenario.text}
{this.state.currentScenario.options[0].text}
)
: (
{this.state.currentScenario.text}
{this.state.currentScenario.options.map((选项,索引)=>(
))}
)
:null
}
);
}
};
因此,我在网上找到了这段代码,它将改变我从路由器获取道具的方式:
HookRouter.js
import * as React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
const RouterContext = React.createContext(null);
export const HookedBrowserRouter = ({ children }) => (
<BrowserRouter>
<Route>
{(routeProps) => (
<RouterContext.Provider value={routeProps}>
{children}
</RouterContext.Provider>
)}
</Route>
</BrowserRouter>
);
export function useRouter() {
return React.useContext(RouterContext);
};
import*as React from'React';
从“react router dom”导入{BrowserRouter,Route};
const RouterContext=React.createContext(null);
导出常量HookedBrowserRouter=({children})=>(
{(路由操作)=>(
{儿童}
)}
);
导出函数useRouter(){
返回React.useContext(RouterContext);
};
新App.js
import React from 'react';
import { withRouter } from "react-router-dom";
import {Routes} from './routes/Routes';
import {HookedBrowserRouter, useRouter} from './routes/HookRouter';
function App() {
const childProps={something: "else"};
return (
<HookedBrowserRouter>
<div className="App">
<Routes childProps={childProps} />
</div>
</HookedBrowserRouter>
);
}
export default withRouter(App);
从“React”导入React;
从“react router dom”导入{withRouter};
从“./Routes/Routes”导入{Routes};
从“./routes/HookRouter”导入{HookedBrowserRouter,useRouter};
函数App(){
const childProps={something:“else”};
返回(
);
}
使用路由器(App)导出默认值;
我用新的Scenario.js让他走得更远
export default class Scenario extends Component {
constructor(props) {
super(props);
this.state = {
scenarios: null,
scenarioId: null,
currentScenario: null
}
}
async componentDidMount() {
const scenarioId = await this.props.match.params.id;
const scenarios = await data.scenarios;
this.setState({scenarios, scenarioId});
this.getScenario();
}
getScenario = () => {
this.state.scenarios.forEach((scenario) => {
if (scenario.id === this.state.scenarioId) {
const currentScenario = scenario;
this.setState({currentScenario});
}
})
}
render() {
return (
<div>
{this.state.currentScenario != null
? this.state.currentScenario.options.length === 1
? (
<div>
<div>{this.state.currentScenario.text}</div>
<div>{this.state.currentScenario.options[0].text}</div>
<a href="/">Go Back</a>
</div>
)
: (
<div>
<div>{this.state.currentScenario.text}</div>
<div>{this.state.currentScenario.options.map((option, index) => (
<div key={index}>
<a href={`/scenario/${option.to}`}>
{option.text}
</a>
</div>
))}</div>
</div>
)
: null
}
</div>
);
}
};
import React, { Component, useState, useEffect } from 'react';
import data from '../data/fake';
import {useRouter} from '../routes/HookRouter';
const RouterContext = React.createContext(null);
const HookSceneario = () => {
const [scenarios, setScenarios] = useState(null);
const [scenarioId, setScenarioId] = useState(null);
const [currentScenario, setCurrentScenario] = useState(null);
// Similar to componentDidMount and componentDidUpdate:
// Update the document title using the browser API
// console.log(React.useContext(RouterContext));
useEffect(() => {
console.log(scenarios);
});
return (
<div>
// ...
</div>
);
}
import React,{Component,useState,useffect}来自'React';
从“../data/fake”导入数据;
从“../routes/HookRouter”导入{useRouter};
const RouterContext=React.createContext(null);
常量HookSceneario=()=>{
const[scenarios,setScenarios]=useState(null);
const[scenarioId,setScenarioId]=useState(null);
常量[currentScenario,setCurrentScenario]=useState(null);
//与componentDidMount和componentDidUpdate类似:
//使用浏览器API更新文档标题
//log(React.useContext(RouterContext));
useffect(()=>{
console.log(场景);
});
返回(
// ...
);
}
因此,
useState
替换类构造函数中的this.state
,而useffect
应该替换componentDidMount
,但我找不到从路由器获取道具的方法。我认为这很好地说明了您正在尝试做的事情:
记住:
由
呈现的组件始终可以访问路由操作(匹配、位置和历史记录)
如果它是由组件
道具渲染的,如
中所示,这是自动的
如果它是由渲染
道具渲染的,则需要展开它们,如中所示:
// You can spread routeProps to make them available to your rendered Component
const FadingRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={routeProps => (
<FadeIn>
<Component {...routeProps}/>
</FadeIn>
)}/>
)
useRouteProps.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import AllRoutes from "./AllRoutes";
function App() {
return (
<Router>
<AllRoutes />
</Router>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React from "react";
import { Switch, Route } from "react-router-dom";
import Home from "./Home";
import Component1 from "./Component1";
function AllRoutes() {
return (
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/comp1" component={Component1} />
</Switch>
);
}
export default AllRoutes;
import React from "react";
import { Link } from "react-router-dom";
function Home(props) {
return (
<div>
I am HOME component
<ul>
<li>
<Link to={"/comp1"}>Component1</Link>
</li>
</ul>
I have access to routeProps: YES
<br />
Because I'm directly rendered from a Route
<ul>
<li>{"props.match:" + props.match.toString()}</li>
<li>{"props.location:" + props.location.toString()}</li>
<li>{"props.history:" + props.history.toString()}</li>
</ul>
</div>
);
}
export default Home;
import React from "react";
import { Link } from "react-router-dom";
import Component1Child from "./Component1Child";
import RouterContext from "./RouterContext";
function Component1(props) {
const routeProps = {
match: props.match,
history: props.history,
location: props.location
};
return (
<RouterContext.Provider value={routeProps}>
<div>
<b>I am Component1</b>
<ul>
<li>
<Link to={"/"}>Home</Link>
</li>
</ul>
I have access to routeProps: YES
<br />
Because I'm directly rendered from a Route.
<br />
And I automatically 'inherit' them when I'm rendered through the Route
'component' prop
<ul>
<li>{"props.match:" + props.match.toString()}</li>
<li>{"props.location:" + props.location.toString()}</li>
<li>{"props.history:" + props.history.toString()}</li>
</ul>
<Component1Child />
</div>
</RouterContext.Provider>
);
}
export default Component1;
import React from "react";
import Component1GrandChild from "./Component1GrandChild";
function Component1Child(props) {
return (
<div>
<b>I am Component1Child</b> <br />
<br />
I have access to routeProps: NO
<br />
Because I'm NOT directly rendered from a Route.
<br />I am rendered by Componen1 and routeProps are not automatically
passed down.
<ul>
<li>{"props.match:" + props.match}</li>
<li>{"props.location:" + props.location}</li>
<li>{"props.history:" + props.history}</li>
</ul>
<Component1GrandChild />
</div>
);
}
export default Component1Child;
import React from "react";
import useRouteProps from "./useRouteProps";
function Component1GrandChild(props) {
const [match, location, history] = useRouteProps();
return (
<div>
<b>I am Component1GrandChild</b> <br />
<br />
I have access to routeProps: YES
<br />
Because I'm consuming the routeProps provided by Component1 (which is the
one directly rendered by the Route)
<br /> And I'm consuming that through a custom hook called useRouteProps.
<br />I am rendered by Componen1 and routeProps are not automatically
passed down.
<ul>
<li>{"props.match:" + match}</li>
<li>{"props.location:" + location}</li>
<li>{"props.history:" + history}</li>
</ul>
</div>
);
}
export default Component1GrandChild;
import React from "react";
const RouterContext = React.createContext(null);
export default RouterContext;
import { useContext } from "react";
import RouterContext from "./RouterContext";
function useRouteProps() {
const routeProps = useContext(RouterContext);
return [routeProps.match, routeProps.location, routeProps.history];
}
export default useRouteProps;
在
的子级中是否需要routeProps
?因为您这样做的方式,因为场景是由
组件渲染的,并且您在render={(routeProps)中传递routeProps
=>
。请注意,我已重命名为routeProps
,以明确渲染中可用的道具
对象是routeProps
(匹配、位置和历史记录)因此,
已经可以访问路由操作
。谢谢@cbdev420的建议。那么你就是编写这段代码的人。我的问题是如何将场景
中的那些道具称为带有挂钩的函数。我似乎无法将控制台.log
中的任何道具称为类。我认为异步生命周期方法是个糟糕的主意……我可以创建单独的异步函数并将此逻辑移到那里