如何重用react路由dom链接的参数到onClick

问题描述 投票:0回答:1

我正在使用react-router-dom

Link
NavLink
v5,并且想要短路
to
参数值以传递给
onClick

这是我的情况:

在我的应用程序中 - 到目前为止,仅

to
参数用于 React Link 和 NavLink。 但是,我有一个新要求,即我需要在单击“链接”或“导航链接”时向外部 iFrame 发送一些事件。

到目前为止我的代码是这样的:

const addVolumeLink = location => ({
    pathname: location.pathname + "/add-volume",
    state: {
        from: location.pathname
    }
});

<Link to={addVolumeLink}>New volume</Link>

但是,当用户单击“新卷”时,我还需要向外部 iFrame 发送一个事件。因此,我天真地通过添加

onClick
监听器来更改此代码,如下所示。

const addVolumeLink = location => ({
    pathname: location.pathname + "/add-volume",
    state: {
        from: location.pathname
    }
});

export const nagivateToParentiFrame = (payload) => {
    window.parent.postMessage({
        type: 'SERVICE:NAVIGATE',
        payload,
    }, "*")
};

<Link to={addVolumeLink} 
      onClick={() => nagivateToParentiFrame({
               pathname: `${window.location.pathname}/add-volume`,
               state: {from: window.location.pathname}})}>
       New volume
</Link>

我正在寻找:是否有办法将

to
参数短路到 onClick。 (注意:这里是一个使用 location 的函数调用。可以是函数调用,也可以是对象)。 原因:我需要在代码中写100处这个onClick。 所以我正在考虑拥有自己的 Link 组件,只需替换
import
而不是到处写这个 onClick (因为我的路径名和状态应该是相同的)。

我尝试过类似的事情(但没有成功):

// 不工作的组件。

import {Link} from "react-router-dom"

const nagivateToParentiFrame = (payload) => {
    window.parent.postMessage({
        type: 'SERVICE:NAVIGATE',
        payload,
    }, "*")
};

export const StyledLinkWithIframeEvent = ({ children, className, style, color, type, large, disabled, tooltip, to, ...rest }) => {
    return <Link
        to={to}
        onClick={() => nagivateToParentiFrame(to)}
        children={children}
        className={className}
        style={style}
        color={color}
        type={type}
        large={large}
        disabled={disabled}
        tooltip={tooltip}
        rest={rest}>
    </Link>
}

组件的用途:

import {StyledLinkWithIframeEvent as StyledLink} from "./myLink"

const addVolumeLink = location => ({
    pathname: location.pathname + "/add-volume",
    state: {
        from: location.pathname
    }
});

const myMainComponent = () => {
   return (<StyledLink to={addVolumeLink}>
         New volume
   </StyledLink>);
}
javascript reactjs react-router-dom
1个回答
0
投票

创建一个自定义链接组件,添加自己的

onClick
处理程序,该处理程序调用您的
navigateToParentiFrame
函数,并传递所传递的
to
属性的结果。

export const navigateToParentiFrame = (payload) => {
  window.parent.postMessage({
    type: 'SERVICE:NAVIGATE',
    payload,
  }, "*")
};
import { Link as BaseLink, useLocation } from 'react-router-dom';
import { navigateToParentiFrame } from '../path/to/navigateToParentiFrame';

const Link = props => {
  const location = useLocation();
  
  return (
    <BaseLink
      {...props}
      onClick={navigateToParentiFrame.bind(
        null,
        typeof props.to === "function"
          ? props.to(location)
          : props.to
      )}
    >
      {props.children}
    </BaseLink>
  );
};
const addVolumeLink = location => ({
  ...location,
  pathname: location.pathname + "/add-volume",
  state: {
    ...location.state,
    from: location.pathname,
  }
});

<Link to={addVolumeLink}>New volume</Link>

const {
  BrowserRouter: Router,
  Switch,
  Route,
  Link: BaseLink,
  useLocation,
} = ReactRouterDOM;

const navigateToParentiFrame = (payload) => {
  console.log("window.parant.postMessage", {
    type: 'SERVICE:NAVIGATE',
    payload,
  }, "*");
};

const Link = props => {
  const location = useLocation();
  
  return (
    <BaseLink
      {...props}
      onClick={navigateToParentiFrame.bind(
        null,
        typeof props.to === "function"
          ? props.to(location)
          : props.to
      )}
    >
      {props.children}
    </BaseLink>
  );
};

const addVolumeLink = location => ({
  ...location,
  pathname: location.pathname + "add-volume",
  state: {
    ...location.state,
    from: location.pathname,
  }
});

//<Link to={addVolumeLink}>New volume</Link>

const App = () => {
 return (
    <React.Fragment>
      <ul>
        <li>
          <BaseLink to="/">Home</BaseLink>
        </li>
        <li>
          <Link to={addVolumeLink}>New volume</Link>
        </li>
      </ul>
    
      <Switch>
        <Route path="/add-volume" render={() => <h1>Add Volume</h1>} />
        <Route path="/" render={() => <h1>Home</h1>} />
      </Switch>
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);

root.render(
  <React.StrictMode>
    <Router basename="/js">
      <App />
    </Router>
  </React.StrictMode>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/5.3.4/react-router-dom.min.js" integrity="sha512-XJ25BbjmZQpaGkOJaDFXVJqfsBebv2aDLsBF3qT6zoC/gVj7XLuefNRzcgmlc5admYuODaYDrap8jzVyOsYFrw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="root" />

© www.soinside.com 2019 - 2024. All rights reserved.