skip to Main Content

I have a function that returns an object containing a component and I am passing props from my function to the component but I see the props coming as an empty object.

export function withBackgroundRed<TProps = any>(
  Component: any,
  props?: TProps
) {
  console.log('props', props);
  return {
    Wrapper: function Wrapper(p = props) {
      console.log('p', p);
      return (
        <div style={{ backgroundColor: 'red' }}>
          <Component {...p} />
        </div>
      );
    },
  };
}

function App(props) {
  return <div>props: {JSON.stringify(props)}</div>;
}

const WithSomeContext = withBackgroundRed(App, { props1: 'props1' }).Wrapper;

export default WithSomeContext;

The first. console.log() print the props as expected, but the second one is just an empty object.

Here a live example

2

Answers


  1. That would be because React will always pass an object with the live props to a component you render.

    So the default value you use for p will never be used, as it will receive the props used (an empty object if no props where passed when rendering the wrapped component).

    You should merge the initial props with the ones provided to to the wrapped component.

    Something like

    export function withBackgroundRed<TProps = any>(
      Component: any,
      props?: TProps
    ) {
      console.log('props', props);
      return {
        Wrapper: function Wrapper(instanceProps) {
          const mergedProps: TProps = Object.assign({}, props, instanceProps);
          console.log('mergedProps', mergedProps);
          return (
            <div style={{ backgroundColor: 'red' }}>
              <Component {...mergedProps} />
            </div>
          );
        },
      };
    }
    

    You can swap the props, instanceProps in the Object.assign depending on which ones you want to prevail in case of conflict.

    Demo: https://stackblitz.com/edit/stackblitz-starters-rlxcy7

    Login or Signup to reply.
  2. There is a more convenient way to do this kind of wrapper:

    
    interface IWrapperProps = {
      Children: React.Element,
      props?: any
    }
    
    const Wrapper = (props: IWrapperProps) => {
    
       return (
          <div style={{ backgroundColor: 'red' }}>
            <Component {...props} />
          </div>
       )
    
    }
    
    const WithSomeContext = (props) => <Wrapper props={props}><App/></Wrapper>
    
    export default WithSomeContext
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search