0.3.0 • Published 9 months ago

templates-for-react v0.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

templates_for_react

It's a small cli to help the creation of react component or xstate machine.

Installation

npm install templates_for_react -g

Usage

cft 
1. Is your version of react >= 18 ? (y/N)
2. Please choose which template to use
    * Component
    * ComponentWithStorybook
    * Context
    * Function
    * Hook
    * StoreZustand
    * Machine
    * AssignXstate
    * GuardXstate
    * useMutation
    * useQuery
3. Please write a name
4.  Select a target directory for your component

Templates Available


Context

Structure Context

[Name]
|--[Name]Provider.tsx
|--use[Name]Context.ts
|--index.ts

Details Context

import * as React from "react";

export interface [Name]ContextProps { }

export const [Name] = React.createContext<[Name]ContextProps>({});

export const [Name]Provider = ({ children }: PropsWithChildren<[Name]ContextProps>) => {
  return <[Name].Provider value={{}}>{children}</[Name].Provider>;
};
import * as React from "react";
import { [Name] } from "./[Name]Provider";

export const use[Name]Context = () => {
  const context = React.useContext([Name]);

  // Uncomment if your context doesn't have reasonable defaults
  //   if (context === undefined) {
  //     throw new Error(
  //       "use[Name]Context must be used within a [Name]Provider"
  //     );
  //   }

  return context;
};
  • index.ts
export { [Name]Provider } from "./[Name]Provider";
export {  use[Name]Context } from "./use[Name]Context";

ComponentStory

Structure ComponentStory

[Name]
|--[Name].spec.tsx
|--[Name].stories.tsx
|--[Name].tsx
|--index.ts

Details ComponentStory

import * as React from 'react';
import { render, screen } from '@testing-library/react';
import [Name], { [Name]Props } from './[Name]';

describe('<[Name] />', () => {
    it('should render', () => {
        const { container }  = render(<[Name] />);
        expect(container).toBeInTheDocument();
    });
});
import * as React from 'react';
import { Meta, Story } from '@storybook/react';
import [Name], { [Name]Props } from './[Name]';

export default {
    title: "/[Name]",
    component: [Name],
} as Meta;

const Template: Story<[Name]Props> = (args) => {
    return <[Name] {...args} />;
};

export const Default = Template.bind({});
import * as React from 'react';

export interface [Name]Props {}

const [Name]: React.FC<[Name]Props> = ({}) => {
    return <div>[Name]</div>
};
  • index.ts
export { [Name] } from "./[Name]";

Component

Structure Component

[Name]
|--[Name].spec.tsx
|--[Name].tsx

Details Component

import * as React from 'react';
import { cleanup, render, screen } from '@testing-library/react';
import { [Name] } from '../[Name]';

describe('[Name]', () => {
    afterEach(() => {
        cleanup();
    });
    it('should render [Name]', () => {
        // Given

        // When
        const { container } = render(<[Name] />);

        //Then
        expect(container).toBeInTheDocument();
    });
});
import * as React from 'react';

export interface [Name]Props {

}

export const [Name]: React.FC<[Name]Props> = () => {
    return (
        <div>
            [Name]
        </div>
    );
};

[Name].displayName = '[Name]';

Function

Structure Function

[Name]
|--[Name].spec.ts
|--[Name].ts

Details Function

import { [Name] } from "./[Name]";

describe('[Name]', () => {
    it('should ', () => {
        
    });
});
export const [Name] = () => {

};

Hook

Structure Hook

use[Name]
|--use[Name].spec.tsx
|--use[Name].tsx

Details Hook

import * as React from "react";

export const use[Name] = () => {
  return () => {
    return 2;
  };
};
import { renderHook } from '@testing-library/react-hooks';
import { [Name] } from './[Name]';

describe('[Name]', () => {
    it('should return 2', () => {
        const { result } = renderHook(() => [Name]());
        const value = result.current();
        expect(value).toEqual(2);
    });
});

__

StoreZustand

Structure StoreZustand

[Name]
|--action
    |--index.ts
    |--setIndex.tsx
|--use[Name].tsx

Details StoreZustand

import create, { StoreApi } from "zustand";
import { setIndex } from "./actions";

interface [Name]State {
    index: number;
};
interface [Name]Actions {
    setIndex: (value: number) => void;
};

const initialState: [Name]State = {
    index: 0,
}

export type [Name]StoreType = [Name]State & [Name]Actions;

export type Set[Name]Store = StoreApi<[Name]StoreType>["setState"];
export type Get[Name]Store = StoreApi<[Name]StoreType>["getState"];

export const use[Name]Store = create<[Name]State & [Name]Actions>(set => ({
    ...initialState,
    setIndex: setIndex(set)
}))
  • action/setIndex.ts
import { Set[Name]Store } from "../use[Name]Store";

export const setIndex = (set: Set[Name]Store) => (value: number) =>
  set(_state => ({
    index: value
  }));
  • action/index.ts
export { setIndex } from "./setIndex";

__

useMutation Hooks

Structure useMutation Hooks

[Name]
|--[Name].spec.tsx
|--[Name].tsx
|--index.tsx

Details useMutation Hooks

import * as React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { MutationCache, QueryCache, QueryClient, QueryClientProvider  } from 'react-query';

const renderWithClient = (client: QueryClient, ui: React.ReactElement) => {
    const { rerender, ...result } = render(
        <QueryClientProvider client={client}>{ui}</QueryClientProvider>
    );
    return {
        ...result,
        rerender: (rerenderUi: React.ReactElement) =>
            rerender(
                <QueryClientProvider client={client}>
                    {rerenderUi}
                </QueryClientProvider>
            ),
    };
};

describe('use[Name]', () => {
    const queryCache = new QueryCache();
    const mutationCache = new MutationCache();
    const queryClient = new QueryClient({ queryCache, mutationCache });

   it("should ", async () => {
    function Page() {
      const { mutate, data = { label: "" } } = use[Name]();

      return (
        <div>
          <h1 data-testid="title">{data["label"]}</h1>
          <button onClick={() => mutate()}>mutate</button>
        </div>
      );
    }
    const { getByTestId, getByText } = renderWithClient(queryClient, <Page />);

    expect(getByTestId("title").textContent).toBe("");
    fireEvent.click(getByText("mutate"));

    await waitFor(() => getByTestId("title"));

    expect(getByTestId("title").textContent).toBe();
  });
});
import { useMutation } from 'react-query';

const [Name] = () => useMutation(() => {
  // return fetch("/api/data") as json
  return "Hello";
}, {
    onMutate: variables => {
        // A mutation is about to happen!
    
        // Optionally return a context containing data to use when for example rolling back
      },
      onError: (error, variables, context) => {
        // An error happened!
        console.log(`rolling back optimistic update with id ${context}`)
      },
      onSuccess: (data, variables, context) => {
        // Boom baby!
      },
      onSettled: (data, error, variables, context) => {
        // Error or success... doesn't matter!
      },
});

export default [Name];
  • --index.tsx
 export { default } from './[Name]';

useQuery Hooks

Structure useQuery Hooks

[Name]
|--[Name].spec.tsx
|--[Name].tsx
|--index.tsx

Details useQuery Hooks

import { QueryClient, QueryClientProvider } from 'react-query';
import { renderHook } from '@testing-library/react-hooks';
import { [Name] } from './[Name]';

const queryClient = new QueryClient();
const wrapper = ({ children }) => (
    <QueryClientProvider client={queryClient}>
        {children}
    </QueryClientProvider>
);

describe('[Name]', () => {
    it('should ', async () => {        
        const { result, waitFor } = renderHook(() => [Name](), { wrapper });

        await waitFor(() => result.current.isSuccess);
        
        expect(result.current.data).toEqual("Hello");
    });
});
import { useQuery } from 'react-query';

const [Name] = () => {
    return useQuery("queryHooks", () => {
        // return fetch("/api/data") as json
        return "Hello";
    });
};

export default [Name];
  • --index.tsx
export { default } from './[Name]';

Machine XState

Structure Machine XState

[Name]
|--actions
    |--actionExample.spec.ts
    |--actionExample.ts
|--guards
    |--guardExample.spec.ts
    |--guardExample.ts
|--services
|--types
    |--index.ts
|--[Name]Machine.ts

Details Machine XState

  • --actions > actionExample.spec.ts
  • --actions > actionExample.ts
  • --guards > guardExample.spec.ts
  • --actions > guardExample.ts
  • --types > index.ts

__

Action Assign XState

Structure Action Assign XState

[Name]Assign
|--[Name]Assign.spec.ts
|--[Name]Assign.ts

Details Action Assign XState

import { TimerContext } from '../../types';
import { ActionTypes } from "xstate";
import { [Name]Assign, [Name]Assignment } from "./assign[Name]";

describe('assign[Name]', () => {
    it('should return object', () => {
        const result = assign[Name];
        expect(result.type).toEqual(ActionTypes.Assign);
    });
    it('should return assignement', () => {
        const context: Context = {
            
        }
        const newContext = assignment[Name](context, { type: ''});
        expect(newContext.).toEqual();
    });
});
import { ActionTypes, AssignAction } from "xstate";

export const [Name]Assignment = (context: Context, event: Event): Partial<Context> => {
    return {
        elapsed: event.value
    };
}

export const [Name]Assign : AssignAction<Context, Event> = {
    type: ActionTypes.Assign,
    assignment: [Name]Assignment
}

__

Guard XState