我正在试着使用React Hooks重构我的代码,但我不太明白如何通过React Routers和Hooks将属性(props)传递给我的组件。
旧的(普通)React代码如下:
App.js
我使用新的Scenario.js已经有了很大进展。
旧的(普通)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);
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>
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;
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>
);
}
};
我在网上找到了一些代码,可以改变我从路由器获取props的方式:
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);
};
新的 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);
我使用新的Scenario.js已经有了很大进展。
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>
);
}
所以,useState
可以替换类构造函数中的this.state
,而useEffect
则应该替换componentDidMount
,但我找不到从路由中获取props
的方法。
<Scenario/>
的子组件中需要routeProps
吗?因为你的渲染方式是在<Route>
组件中渲染的,而你是通过render={(routeProps) => <C {...routeProps)/>
传递routeProps
的。请注意,我已将其重命名为routeProps
,以明确render
属性中可用的props
对象即为routeProps
(匹配、位置和历史记录)。因此,<Scenario/>
已经可以访问routeProps
。 - cbdeveloperScenario
内的这些props作为函数调用。似乎我不能像使用类一样console.log
任何props。 - Viet