Search code examples
reactjsreduxreact-reduxreact-boilerplate

Dispatching components via react-redux


I want to pass a component and display it inside another one through redux. I am doing something like this:

ComponentToDispatch.js

const ComponentToDispatch = (props) => {
    return (<div>Propagate me {props.anthem}</div> {/* props.anthem = undefined, unlike what I expect.*/}
);
};
export {ComponentToDispatch};

In the following component, I have a button that dispatches the formerly defined one.

BruitEvent.js

 // code above
`import {ComponentToDispatch} from "./ComponentToDispatch";
 import {showComponentAction} from "./actions";
 const BruitEvent =()=>{
    const dispatch = useDispatch();
    return (<button onClick={(evt)=>dispatch(showComponentAction(ComponentToDispatch)}>
 Click to dispatch</button>);
 };`

The action that triggers this event is: actions.js

 `
 export function ShowComponentAction(Component) {

 return {
    type: SHOW_ACTION,
    payload: {
      component: <Component />,
  },
 };
}`

Finally, I can display the propagated component:

const DispayComponent = () =>{
const { component} = useSelector((state) => {
if (state.testDisplay) {
  return {
    component: state.testDisplay.component,
  };
}
   return { component: null };
 });

useInjectReducer({ key: "testDisplay", reducer });

   return (<div>{component}</div>);
 }
 export {DisplayComponent};

So far so good, thanks to David Hellsing for his insight, I can display every static thing resides in `ComponentToDispatch', but it fails to handle props.

Question: How can I transmit props while dispatching component itself?


Solution

  • You need to either instantiate and enclose the props before the component is dispatched, or pass the uninstantiated component and props object in the dispatched action and pass the props to the component on the receiving end. I suggest the latter, send both component and props in action.

    const BruitEvent =()=>{
      const dispatch = useDispatch();
      return (
        <button
          onClick={(evt) => dispatch(
            showComponentAction(ComponentToDispatch, /* some possible props object */)
          )}
        >
          Click to dispatch
        </button>
      );
    };
    
    ...
    
    export function ShowComponentAction(Component, props = {}) {
      return {
        type: SHOW_ACTION,
        payload: { Component, props }, // <-- assumes reducer places in state.testDisplay
      },
    };
    
    ...
    
    const DispayComponent = () =>{
      const { Component, prop } = useSelector((state) => state.testDisplay);
    
      useInjectReducer({ key: "testDisplay", reducer });
    
      return Component ? <div><Component {...props} /></div> : null;
    }