React-Router-DOM v6使用useNavigate将值传递给另一个组件

86

react-router-dom的版本是v6,我在使用Navigate传递值到另一个组件时遇到了问题。

我想将选定的行传递到名为Report的另一页。但是,我不确定是否在使用方法时使用了正确的语法,也不知道如何在Report组件中获取该状态。

Material-ui表格:我正在尝试在onClick参数中使用redirectToReport(rowData)

function TableRows(props){
return (
    <MaterialTable
        title="Leads"
        columns={[
            ...
        ]}
        data = {props.leads}       
        options={{
            selection: true,
            filtering: true,
            sorting: true
        }}
        actions = {[{
            position: "toolbarOnSelect",
            tooltip: 'Generate a report based on selected leads.',
            icon: 'addchart',
            onClick: (event, rowData) => {
                console.log("Row Data: " , rowData)
                props.redirect(rowData)
            }
        }]}
    />
)}

LeadTable组件
export default function LeadTable(props) {
let navigate = useNavigate();

const [leads, setLeads] = useState([]);
const [loading, setLoading] = useState(true);    

async function fetchUrl(url) {
    const response = await fetch(url);
    const json = await response.json();

    setLeads(json[0]);
    setLoading(false);
}

useEffect(() => {
    fetchUrl("http://localhost:5000/api/leads");
}, []);

function redirectToReport(rowData) {
    navigate('/app/report', { state: rowData }); // ??? I'm not sure if this is the right way
}

return(
    <div>
        <TableRows leads={leads} redirect={redirectToReport}></TableRows>
    </div>
)}

报告组件
export default function ReportPage(state) {
return (
    <div>
        { console.log(state) // This doesn't show anything. How to use the state that were passed from Table component here?}
        <div className = "Top3">
          <h3>Top 3 Leads</h3>
            <ReportTop3 leads={[]} />
        </div>
    </div>
);}
8个回答

144

6 版本的 react-router-dom

我知道这个问题已经得到回答,但我觉得这可能对那些想要使用功能组件并正在寻找通过 react-router-dom v6 传递数据的例子的人有所帮助。

假设我们有两个功能组件,第一个组件 A,第二个组件 B。组件 A 想要向组件 B 共享数据。

钩子的用法:(useLocation,useNavigate)


import {Link, useNavigate} from 'react-router-dom';

function ComponentA(props) {

  const navigate = useNavigate();

  const toComponentB=()=>{
navigate('/componentB',{state:{id:1,name:'sabaoon'}});
  }

  return (
   <>
<div> <a onClick={()=>{toComponentB()}}>Component B<a/></div>
</>
  );


}


export default ComponentA;

现在我们将从组件B中获取数据。

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

 function ComponentB() {

    const location = useLocation();
   
        return (

            <>
               
<div>{location.state.name}</div>

            </>
        )
    }

export default ComponentB;

注意:如果您正在使用类组件,则可以使用HOC,因为钩子无法在类组件中工作。


84

我认为你的navigate('/app/report', { state: rowData });是正确的。

react-router-v6

如果你需要状态,请使用navigate('success', { state })

navigate

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: any }
  ): void;
  (delta: number): void;
}
您的ReportPage需要在进行推送的组件所在的相同Router下呈现。
由于现在将路由道具作为JSX文字传递,因此不再将它们传递给呈现的组件。要访问路由状态,必须通过useLocation钩子进行访问。
function ReportPage(props) {
  const { state } = useLocation();
  console.log(state);

  return (
    <div>
      <div className="Top3">
        <h3>Top 3 Leads</h3>
        <ReportTop3 leads={[]} />
      </div>
    </div>
  );
}

如果组件无法使用React hooks,则仍可通过自定义withRouter高阶组件访问路由状态。这是一个简单的withRouter HOC示例,将location作为属性传递。

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

const withRouter = WrappedComponent => props => {
  const location = useLocation();
  // other hooks

  return (
    <WrappedComponent
      {...props}
      {...{ location, /* other hooks */ }}
    />
  );
};

然后像在RRDv6之前那样通过props进行访问。

class ReportPage extends Component {

  ...

  render() {
    console.log(this.props.location.state);

    return (
      <div>
        <div className="Top3">
          <h3>Top 3 Leads</h3>
          <ReportTop3 leads={[]} />
        </div>
      </div>
    );
  }
}

2

2件事情(只是一个建议): 与其使用三元运算符,不如使用 &&。

{location && <div>{location.state.name}</div>}

为什么要检查位置并呈现位置的状态名称?我会在获取数据时使用检查,或确保数据返回 null 或您的值。

这不是与问题相关的答案,甚至更多地说,它本身就是一种观点。 - ncubica

2
我偶然发现了这篇文章,我按照上面建议的一切去做,但出于某种原因,它仍然无法正常工作。在我要路由到的组件中使用 useLocation 时,我得到了 nulllocation?.state。我正在使用 MUI DataGrid,在 onRowClick 中我正在执行以下操作。
onRowClick={(rowData) => {
  if (rowData) navigate('/some/page', { state: { data: rowData } })
}

我一直在控制台记录rowData,并发现里面有一个对象!!但它仍然是null。我非常困惑。后来我意识到我并不需要从rowData对象中获取所有的东西,所以我做了这个:
onRowClick={(rowData) => {
  if (rowData) navigate('/some/page', { state: { data: rowData.row } })
}

使用rowData.row更新数据,而不是整个网格数据,解决了问题。回想起来,我应该为onRowClick重命名rowData,因为最初我认为它只是传递行数据。

我发帖的目的是,如果有其他人使用MUI并尝试通过路由器传递行时遇到此问题,并且在遵循所有建议后仍然看到null,则可以参考此解决方案。


你解决了这个问题吗? - undefined

1

在 Sabaoon Bedar 的回答中,您可以在显示数据之前检查是否有数据:

  • 不要使用这个代码:<div>{location.state.name}</div>

  • 使用这个代码:{ location != null ? <div>{location.state.name}</div> : ""}


1

如果你想在函数组件中使用 useNavigate 发送数据,可以像这样使用:

navigate(`/take-quiz/${id}`, { state: { quiz } });

然后你可以使用 useLocation 钩子来获取它:

const location = useLocation();

location.state.quiz 就是你的数据。

但是你不能通过 props 获取这些数据,这是一个棘手的部分 ;)!!


1
在最新版本的react-router-dom@6中,你可以使用useNavigate()钩子来重定向到另一个页面。 useNavigate()钩子返回一个函数,让你以编程方式导航到其他页面,并携带一些状态,例如:
import { useNavigate } from "react-router-dom";
 
const navigate = useNavigate();
...
navigate('/', {state: id});

基本上,这个导航函数接受两个参数。第一个参数是声明一个路径"/",用于告诉要导航到哪里,第二个参数是可选的,你可以在花括号中传递一些状态(比如{state: id})如果你想要的话。 访问数据: 使用useLocation()钩子来访问子组件中存在的状态或数据。 首先,你需要导入一个useLocation()钩子,该钩子用于访问数据或状态的组件。该钩子返回当前位置对象。
import { useLocation } from "react-router-dom";

const { state } = useLocation();
       // OR
const location = useLocation();

然后,我们可以轻松地获取location对象中的状态或数据,就像这样 - location.state
要了解更多信息,只需查看他们的文档 -

https://reactrouter.com/en/main/hooks/use-navigate

https://reactrouter.com/en/main/hooks/use-location


0

在SABAOON BEDAR的回答中,

from component A: navigate('/', {state:"whatever"} 

在组件B中:console.log(location.state) //输出 = 任何内容


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接