1

I have a helper function which is utilized by two components in my React app. And this helper function dispatches a set of Redux actions. How do I connect React-Redux to this helper function so that it can dispatch actions?

My helper looks like this:

export default const helper = () => {
   //dispatch some actions
   // I would like to do something similar to  this: this.props.dispatch()
   //do something else(produce some JSX)
}

My component look like this:

 import helper from './helper.js';

 export default class Example extends React.Component {
   return (
      {helper()}
   );
 }

My component 1 look like this when the helper is defined inside the component itself:

 import { setTime } from '../actions/setTime.js';

 class Example1 extends React.Component {
   helper() {
     //actions are synchronous
     this.props.setTime('10:00PM');

     return (<h1>hello</h1>);
   }

   render() {
     return (
      <h1>something</h1>
      {helper()}
     );
   }
 }

 const mapDispatchToProps = (dispatch) => {
   return {
      setTime: (time) => (dispatch(setTime(time)))
   };
 }

 export default connect(null, mapDispatchToProps)(Example1);

My component 2 look like this when the helper is defined inside the component itself:

 import { setTime } from '../actions/setTime.js';

 class Example2 extends React.Component {
   helper() {
     //actions are synchronous
     this.props.setTime('10:00PM');

     return (<h1>hello</h1>);
   }

   render() {
     return (
      {helper()}
     );
   }
 }

 const mapDispatchToProps = (dispatch) => {
   return {
      setTime: (time) => (dispatch(setTime(time)))
   };
 }

 export default connect(null, mapDispatchToProps)(Example2);

Example1 and Example2 renders based on Route change. You might be thinking I can use the higher order component but I cannot because these two components have different state and renders different things.

Please note that I want to have access to the dispatch function in the helper method and I am not accessing Redux state from that component so I do not have to worry about state change(mapStateToProps is not in use).

loveTrumpsHate
  • 601
  • 3
  • 11
  • 15
  • Without your code, it is hard to say. Is your helper function a dispatcher that you can map to your props? Is it how you should use `connect( mapStateToProps, mapDispatchToProps )( Component )` you are asking? – Icepickle Dec 06 '18 at 19:37
  • @Icepickle please see edit – loveTrumpsHate Dec 06 '18 at 19:41
  • So you are looking for some way to add `dispatch` to your helper method? You really don't want to dispatch some actions from your rendering method, as it could change the state of your component and create some kind of continuous / endless render -> dispatch -> state update -> render -> dispatch ... If you wish to create jsx based on a certain state, maybe your helper should do only that, and you can pass the current state in? – Icepickle Dec 06 '18 at 19:44
  • @Icepickle Please note I am not accessing Redux state from that component so I do not have to worry about state change(mapStateToProps is not in use). And yes, I want to have access to the dispatch function in the helper method. – loveTrumpsHate Dec 06 '18 at 19:47
  • Can you give more input code about what your helper function is doing? I would pass helper as 2 second argument of `connect`, I think that would be the most easy way to do it, your helper function would then get dispatch as a first argument (but then you could dispatch from inside your component instead) – Icepickle Dec 06 '18 at 19:51
  • @Icepickle Yes, I think that would work. Let me try that. – loveTrumpsHate Dec 06 '18 at 19:57
  • @Icepickle please see edit – loveTrumpsHate Dec 06 '18 at 20:03
  • Can you give a bit more input on what you are trying to achieve with the helper function and what you need the dispatches for? – Icepickle Dec 06 '18 at 20:20
  • @Icepickle the helper is common to two components so I want to move the helper function to a separate module. – loveTrumpsHate Dec 06 '18 at 20:21
  • @Icepickle I want the dispatchers in the helper function so that I can dispatch some actions to Redux store to update the Redux state. The Redux state is used by other components, not these two. – loveTrumpsHate Dec 06 '18 at 20:22
  • But isn't that exactly what you're doing at this moment? – Icepickle Dec 06 '18 at 20:24
  • @Icepickle everything works fine when the helper function is defined inside the component – loveTrumpsHate Dec 06 '18 at 20:25
  • @Icepickle but I decided to move the helper function to a separate module so that the other component also make use of this helper function. – loveTrumpsHate Dec 06 '18 at 20:25
  • react-redux `connect` is supposed to be used with components. It relies on component hierarchy. Due to how you use `helper`, you most likely have XY problem that should be solved in another way. `helper` could be a component, or else. You can access `dispatch` directly on a store but this may be not a good idea. – Estus Flask Dec 06 '18 at 20:34
  • @estus please upvote the question – loveTrumpsHate Dec 06 '18 at 20:38
  • I'll do. Consider explaining in the question why you decided to go with `helper` function instead of `Helper` component. As I mentioned, this seems to be XY problem and possibly the reason why it was downvoted. – Estus Flask Dec 06 '18 at 20:40
  • @Icepickle If I use the helper function with connect then I won't be able to send arguments to it. – loveTrumpsHate Dec 06 '18 at 20:40
  • @estus It is not a component. It is a function that takes some arguments and It returns an array of JSX elements – loveTrumpsHate Dec 06 '18 at 20:41
  • I'm not sure what you mean. You don't use an array anywhere in the code you posted. – Estus Flask Dec 06 '18 at 20:43

2 Answers2

2

This is XY problem.

react-redux and connect are supposed to be used with components, it relies on component hierarchy (React context) to provide a store to components. connect isn't supposed to be used with functions that don't belong to component hierarchy.

It's possible to access store.dispatch directly in helper function but this indicates design problem because it's low level API that isn't supposed to be used directly in React

Component composition is idiomatic way to compose functionality in React. helper function performs a side effect (dispatches an action) and returns an element. It can be expressed as connected component:

const Helper = props => {
 props.setTime('10:00PM');

 return (<h1>hello</h1>);
};


 const mapDispatchToProps = (dispatch) => {
   return {
      setTime: (time) => (dispatch(setTime(time)))
   };
 }

export default connect(null, mapDispatchToProps)(Helper);
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
1

I had a similar problem, i resolve it by passing this to helper function. If u need to dispatch it by action something like example could help.

export default const helper = (that) => {
   return <button onClick={()=>that.props.YourDispatch()}/>
}

import helper from './helper.js';

export default class Example extends React.Component {
   return (
      {helper(this)}
   );
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
noon
  • 11
  • 1