Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React使用React挂钩从路由器获取道具_Javascript_Reactjs_React Router_React Hooks - Fatal编程技术网

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
中的任何道具称为类。我认为异步生命周期方法是个糟糕的主意……我可以创建单独的异步函数并将此逻辑移到那里