Code Monkey home page Code Monkey logo

react-slot-component's Introduction

react-slot-component

Vue inspired slot like high order component for React

NPM JavaScript Style Guide Badges Badges Badges Badges Badges Badges

Install

npm install --save react-slot-component
yarn add react-slot-component

Usage

The aim of this package is to end up with annoying practice of passing the subcomponents to the layouts using properties. The package allows you to create and use layouts with replaceable default slots with pure JSX/TSX syntax.

Prepare your Layout

// SlotExampleComponent.tsx

import * as React from 'react';
import { withSlots } from 'react-slot-component';

export type SlotExampleComponentProps = {};

// Describe you future slots name with props

export type SlotExampleComponentSlots = {
  SlotOne: {
    children: React.ReactNode;
    slotOneProp1: string;
    slotOneProp2: string;
  };
  SlotTwo: {
    children: React.ReactNode;
    slotTwoProp1: string;
    slotTwoProp2: string;
  };
};

export const SlotExampleComponent = withSlots<
  SlotExampleComponentSlots,
  SlotExampleComponentProps
>(props => {
  const {
    children,
    // All future slot props passed via slotProps prop
    slotProps,
  } = props;

  return (
    <div>
      {slotProps.SlotOne ? (
        <div>
          <div>{slotProps.SlotOne.slotOneProp1}</div>
          <div>{slotProps.SlotOne.slotOneProp2}</div>
          <div>{slotProps.SlotOne.children}</div>
        </div>
      ) : (
        <div data-test="SlotOneDefaultContent">SlotOneDefaultContentValue</div>
      )}
      {slotProps.SlotTwo ? (
        <div>
          <div>{slotProps.SlotTwo.slotTwoProp1}</div>
          <div>{slotProps.SlotTwo.slotTwoProp2}</div>
          <div>{slotProps.SlotTwo.children}</div>
        </div>
      ) : (
        <div>SlotTwoDefaultContentValue</div>
      )}

      {children}
    </div>
  );
});

Use in app with replaced layout parts

// App.tsx
import React from 'react';

import { SlotExampleComponent } from './SlotExampleComponent';

export const App = () => {
  return (
    <SlotExampleComponent {...args}>
      <SlotExampleComponent.SlotOne
        slotOneProp1="slotOneProp1Value"
        slotOneProp2="slotOneProp2Value"
      >
        SlotOneChildrenValue
      </SlotExampleComponent.SlotOne>
      <SlotExampleComponent.SlotTwo
        data-test="SlotTwo"
        slotTwoProp1="slotTwoProp1Value"
        slotTwoProp2="slotTwoProp2Value"
      >
        SlotTwoChildrenValue
      </SlotExampleComponent.SlotTwo>
      SlotExampleChildrenValue
    </SlotExampleComponent>
  );
};

Optionally allow replace slot components with same name to override each other

This is especially useful for route transitions, where you briefly have both routes in DOM at the same time.

License

MIT ยฉ kolengri

react-slot-component's People

Contributors

kolengri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

devnomic zian502

react-slot-component's Issues

Thank you! My components sweet again!

Coming from vue, just to say thanks, i think this even should be included in react by default.
Usual component namespacing cannot handle complex structure like this lib which is sorely needed for clean and sweet code.

Btw, any reason why the naming of withSlot using camel case instead of WithSlot?

[bug] Component not re-rendered when component props is changed, only when slot props is changed

Suppose you have created Modal component using react-slot-component
and you want to toggle it's state using a button

const [isOpen, setIsOpen] = useState(false);

<button onClick={() => setIsOpen(true)}>Show modal</button>
<Modal isOpen={isOpen}>
  <Modal.Body>Hello</Modal.Body>
</Modal>

Strangely it won't work as expected, only if it's slot props changed it will re-render. (E.g. Modal.Body).
code below will work as expected.

const [isOpen, setIsOpen] = useState(false);

<button onClick={() => setIsOpen(true)}>Show modal</button>
<Modal isOpen={isOpen}>
  <Modal.Body isOpen={isOpen}>Hello</Modal.Body>
</Modal>

I think it's because of createResultComponent memo function.
So i tried to modify the source code like below, it works, is this patch correct?

const { children: prevPropsChildren, slotKeys: prevPropsSlotKeys, ...prevOtherProps } = prevProps;
const { children: nextPropsChildren, slotKeys: nextPropsSlotKeys, ...nextOtherProps } = nextProps;

const prevSlots = getSlotProps(prevPropsChildren, prevPropsSlotKeys);
const nextSlots = getSlotProps(nextPropsChildren, nextPropsSlotKeys);
const prevCleanChildren = getCleanChildren(prevPropsChildren, prevPropsSlotKeys);
const nextCleanChildren = getCleanChildren(nextPropsChildren, nextPropsSlotKeys);
return (
  deepEq(prevOtherProps, nextOtherProps) &&
  deepEq(prevSlots, nextSlots) &&
  deepEq(prevCleanChildren, nextCleanChildren)
);

Not working with React 19

It seems that this will stop working, as soon as React 19 comes out. Tested with 19.0.0-beta-94eed63c49-20240425 slotProps is always {}, which leads to rendering nothing, obviously.

I was forced to upgrade to React 19 upgrade beta due to other issues. Does react-slot-component intend to support React 19?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.