【问题标题】:Can I connect just the onClick function to the Redux store, instead of connecting the button component?我可以只将 onClick 函数连接到 Redux 商店,而不是连接按钮组件吗?
【发布时间】:2018-09-19 08:20:03
【问题描述】:

我正在使用 react-redux 连接我的 Redux 存储中的数据。我发现了如何连接选择器(如mapStateToProps),以便在我需要时可以在 React 组件中作为道具使用数据。

我有一个 React 按钮组件,并且我已经为它提供了道具。从其他答案中,我想我可以看到如何指定 onClick 函数,以便 eventHandler 可以访问这些道具。

但是我意识到按钮本身并不需要这些道具,而需要它们的只是 onClick 事件。有没有办法将 onClick 函数连接到 Redux 商店而不是连接按钮组件?

我尝试了几种方法,但在类、函数、HOC、组合等方面有点迷失。

更新

更多上下文:在任何用户会话中,我对此 onClick 函数感兴趣的状态(地理)最初是从数据库中获取的,然后几乎没有改变。我想要实现的 onClick 操作是基于此地理数据的。如果地理数据确实发生了变化,那么 DOM 中的几乎所有内容都需要重新渲染。


感谢您的 cmets - 我进行了更多探索,并设法在名为 TestOnClick 的代码沙盒中创建了一个框架应用程序。我想这可能是我的问题的一个答案。

在应用中有两个按钮

  • 一个人从商店获取数据作为道具,并像@lecstor 向我展示的那样使用它们投资 onClick 函数 - 我想这是相当标准的东西,但我是 React 的新手
  • 另一个没有这样的 props,但调用了一个 onClick 函数,该函数本身使用 getState() 从 store 中获取相同的数据

两者似乎都可以扩展以做我想做的事,因为他们拥有做这件事所需的一切。 IF 所以我打算使用第二种按钮方法,其中按钮本身没有道具。

据我了解,使用 getState 而不是 connect 意味着如果 store 中的数据发生变化,Redux 不会通知我的函数重新渲染。但我不认为这是一个问题,因为作为一个 onClick 函数,没有什么需要渲染的,而且无论如何几乎整个 DOM 都需要重新渲染。我是否理解正确?

更新 2 我试图在我的真实项目中使用无道具按钮方法并面临循环依赖,所以它可能不是一个有效的答案。进一步探索。

【问题讨论】:

  • 你能分享你的代码吗?也许在codesandbox.io 或者社区可以参考的github repo?传递道具并调用 onClick 函数并将道具作为参数传递给它是非常基本的,但不确定您可能做错了什么。
  • @SivcanSingh 我同意共享代码,但是您也可以在这里轻松地做到这一点,我在一年前创建了一个default playground on codereview,当我必须实施时我经常使用它作为答案的一部分的 react/redux sn-p ;)
  • @Icepickle 干得不错。将测试它。而 OP 可以将代码移到那里,让其他人轻松帮助他。
  • 谢谢。不幸的是,我无法理解如何处理默认 playgound,所以我将尝试将我的应用程序的相关部分放入代码和框。
  • 好吧,您应该始终在问题本身中添加相关代码。您可以在此处使用 stacksn-ps 来获得 minimal reproducible example 的可运行版本(因此您不应该提供所有这些,只是您被卡住的部分以及可以轻松复制的部分,以便我们回答您的问题)

标签: javascript reactjs redux react-redux


【解决方案1】:

您可以纯粹使用按钮来调用组件中的函数,该函数从道具或状态中读取数据/函数。

class Form extends Component {
  state = { name: "Fred" };

  onClick = () => {
    const { name } = this.state;
    const { userId, saveUser } = this.props;
    saveUser({ userId, name });
  };

  render() {
    return <button onClick={this.onClick}>Save Me</button>;
  }
}

【讨论】:

  • 谢谢,这很有用。但是,我最理想的情况是,我是否可以在没有任何道具的情况下离开按钮并连接 onClick 函数本身以从商店中获取道具。
  • @PeterCooper 您的onClick 函数如何知道如何处理点击?在某个地方,您必须使用获取正确数据的处理程序来满足事件。这里的代码是最容易处理的解决方案,因为按钮只会添加适当的处理程序。唯一的挑剔是我们甚至没有OP的代码,因此很难根据猜测提供答案
  • @PeterCooper,此时我不得不问,你想要达到什么目的?您需要从 dom 获得“点击”到您的组件代码,没有太多的解决方法。唯一的选择是用另一个元素包裹你的按钮,这个元素和我们在这里做的一样,但是当它冒泡时作用于事​​件。
  • 我在我的原始帖子中添加了一个更新,提供了更多背景信息和一些进一步的探索。
【解决方案2】:

如果我错了,请纠正我:您想将所需的最少道具传递给您的 Button 组件。理想情况下,只有单个函数可以访问state.geography.place,但不能访问状态。

如果你使用advanced connect options这是可能的

const mapStateToProps = state => ({
  opsdetails: placeSelector(state)
});

const mapDispatchToProps = dispatch => ({
  alertPlace(opsdetails) {
    console.log(opsdetails);
    alert(
      `Place via WithPropsButton is ${opsdetails.OPSCode}) ${
        opsdetails.OPSName
      }`
    );
    //dispatch(YOUR_ACTION)
  }
});

const mergeProps = (stateProps, dispatchProps, ownProps) => ({
  ...ownProps,
  alertPlace: () => dispatchProps.alertPlace(stateProps.opsdetails)
});

export default connect(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps
)(WithPropsButton);

WithPropsButton 获取从mergeProps 函数返回的道具,即直接传递给它的任何自己的道具和alertPlace 函数。

这还允许简化组件并使其成为无状态函数:

const WithPropsButton = ({ alertPlace, ...remaining }) => (
  <button onClick={alertPlace} {...remaining}>
    With Props
  </button>
);

要记住的一件事:

alertPlace function prop 将在每次state.geography.place 更改时重新创建,因此如果连接的有状态组件很复杂,您希望避免重新渲染过于频繁(在这种情况下不是使用简单的按钮)进一步的更改是需要。

为避免重新渲染,您可以实现一个 shouldComponentUpdate 来忽略 alertPlace 道具更新。

我分叉了你的代码框并实现了我在这里谈论的内容。 请看https://codesandbox.io/s/pk60228qk0

【讨论】:

    【解决方案3】:

    如果不需要映射任何Props,可以使用null作为connect函数的第一个参数:

    MyConnectedComponent = connect(
        null,
        mapDispatchToProps
    )(MyComponent)
    

    【讨论】:

    • 虽然这个 sn-p 可以回答这个问题,但没有任何解释的 sn-p 被认为是低质量的帖子,请查看。
    猜你喜欢
    • 2019-12-14
    • 2016-04-02
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多