如何导航到另一个组件并传递数据

How to navigate to another component and pass data

我目前正在尝试完成从组件到组件的路由并传递数据,以便新打开的组件可以使用它。经过几个小时的研究,我偶然发现了一些对我的情况不起作用的解决方案。

在我的应用程序中,我有两个页面:主页和搜索。该应用程序由几个不同的组件层组成,例如:App.js -> imports Home.js -> imports Body.js。 App.js 使用 React Router 定义路由。主页的主体包含一个搜索栏。执行搜索时,应用程序获取数据并需要将此数据传递到将显示它的搜索页面。请参阅以下文件:

App.js

import React from "react";
import {
    BrowserRouter as Router,
    Routes,
    Route
} from "react-router-dom";

/* Import Components */
import Home from "./templates/home/Home.js";
import Search from "./templates/search/Search.js";

class App extends React.Component {
    render() {
        return (
            <Router>
                <Routes>
                    <Route path="/home" element={<Home />} />
                    <Route path="/" element={<Search/>}/>
                </Routes>
            </Router>
        );
    }
}

export default App;

Home.js

import React from "react";

/* Import Components */
import Header from "../header/Header.js";
import Body from "./body/Body.js";
import Footer from "../footer/Footer.js";

class Home extends React.Component {
    render() {
        return (
            <div>
                <Header />

                <Body />

                <Footer />
            </div>
        );
    }
}

export default Home;

正文

import React from "react";
import { Container, Row, Col } from "react-bootstrap";
import './body.css';
import { Navigate } from "react-router-dom";

/* Import Components */
import TitleImage from "./titleImage/TitleImage";
import SearchBar from "./searchBar/SearchBar";
import SampleOccurrence from "./sampleOccurence/SampleOccurence";

/* Import API functions */
import SpecimenSearch from "../../../api/SpecimenSearch.js";

class Body extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            searchQuery: ''
        }
    }

    updateSearchQuery(query) {
        this.setState({
            searchQuery: query.target.value
        });
    }

    handleSearch() {
        const searchQuery = this.state.searchQuery;

        SpecimenSearch(searchQuery, process.bind(this));

        function process(result) {
            this.setState({
                searchResults: result
            });
        }
    }

    render() {
        const items = [
            'Frogger', 'Frogger', 'Frogger',
            'Frogger', 'Frogger', 'Frogger',
            'Frogger', 'Frogger', 'Frogger'
        ];

        if (!this.state.searchResults) {
            return (
                <>
                    <TitleImage />
                    <Container fluid>
                        <SearchBar
                            onSearch={() => this.handleSearch()}
                            updateSearchQuery={(query) => this.updateSearchQuery(query)}
                        />

                        <Row>
                            <Col md={{ span: "10", offset: "1" }} className="sampleOccurences">
                                <Row>
                                    <h3 className="sampleOccurencesTitle">
                                        Explore froggies
                                    </h3>
                                </Row>
                                <Row>
                                    {items.map((value, index) => {
                                        return <SampleOccurrence />
                                    })}
                                </Row>
                            </Col>
                        </Row>
                    </Container>
                </>
            );
        } else {
            // console.log(this.state.searchResults);
            // return(
                // <Navigate to="/" state={{data: this.state.searchResults}} />
                // <Search searchResults={this.state.searchResults} />
            // );
        }
    }
}

export default Body;

如您在 Body.js 中所见,我要么尝试使用 useNavigate 挂钩将页面导航到搜索并呈现 <Navigate to='/' /> 元素('/' 是搜索的设置路径页)。钩子不起作用,因为钩子根据 React 组件中不允许的 React。后者在链接到搜索页面时工作正常,但无法传递数据(例如传递给 <Search /> 的道具)。

如何使用 React Router 从 Body.js 导航到 <Search /> 页面并传递数据(对象数组)?

为了您的目标,我不会使用 react-router 来传递数据。我会考虑使用状态管理库或上下文。

但是,您可以通过两种方式完成此操作:

  1. 功能组件(带钩子) 使用来自 useNavigate()
  2. options.state

示例

// body.js
navigate('/search', { state: {
data: [{id: 1, value: '1'}, {id: 2, value: '2'}]
} });

// search.js
const location = useLocation();
const {data} = location.state; 
// data => [{id: 1, value: '1'}, {id: 2, value: '2'}]
  1. Class 组件

使用 <Navigate../>

中的 options.state

示例

// body.js
 <Navigate to="/search" state={{
data: [{id: 1, value: '1'}, {id: 2, value: '2'}]
}} />

...

Tom,可以从 location 对象访问传递的路由状态,即 location.state.data。您使用 useLocation 挂钩访问接收组件中的 location 对象。

发件人:

<Navigate to="/" state={{ data: this.state.searchResults }} />

接收者:

import { useLocation } from 'react-router-dom';

...

const { state } = useLocation();
const { data } = state || {};

如果接收组件是一个 class 组件并且不能直接使用 useLocation 那么你可以创建一个自定义的 withRouter 高阶组件来为你处理这个并通过 location 下来作为道具.

示例:

import { useLocation, /* other hooks */ } from 'react-router-dom';

const withRouter = Component => props => {
  const location = useLocation();
  // other hooks
  return <Component {...props} {...{ location, /* ...other hooks */ }} />;
};

export default withRouter;

用这个 withRouter HOC 装饰 Search 组件。

export default withRouter(Search);

现在 location 作为 prop 注入。通过 this.props.location.state 访问路由状态,与上面类似。