diff --git a/.prettierrc.js b/.prettierrc.js index cd58a0d..ba9390b 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -5,7 +5,7 @@ const config = { importOrderSeparation: true, importOrderSortSpecifiers: true, bracketSpacing: false, - printWidth: 120, + printWidth: 100, semi: true, singleQuote: false, trailingComma: "all", diff --git a/README.md b/README.md index 1db53cc..42bf28b 100644 --- a/README.md +++ b/README.md @@ -1,160 +1,77 @@ -# TSDX React User Guide +# 🔀 React use bireducer [![tests](https://img.shields.io/github/workflow/status/soywod/react-use-bireducer/integration?label=tests&logo=github&style=flat-square)](https://github.com/soywod/react-use-bireducer/actions/workflows/test.yaml) [![codecov](https://img.shields.io/codecov/c/github/soywod/react-use-bireducer?logo=codecov&style=flat-square)](https://app.codecov.io/gh/soywod/react-use-bireducer) [![npm](https://img.shields.io/npm/v/react-use-bireducer?logo=npm&label=npm&color=success&style=flat-square)](https://www.npmjs.com/package/react-use-bireducer) -Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it. +React hook for managing effects within reducers. -> This TSDX setup is meant for developing React component libraries (not apps!) that can be published to NPM. If you’re looking to build a React-based app, you should use `create-react-app`, `razzle`, `nextjs`, `gatsby`, or `react-static`. - -> If you’re new to TypeScript and React, checkout [this handy cheatsheet](https://github.com/sw-yx/react-typescript-cheatsheet/) - -## Commands - -TSDX scaffolds your new library inside `/src`, and also sets up a [Parcel-based](https://parceljs.org) playground for it inside `/example`. - -The recommended workflow is to run TSDX in one terminal: +## Installation ```bash -npm start # or yarn start +yarn add react-use-bireducer +# or +npm install react-use-bireducer ``` -This builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`. - -Then run the example inside another: - -```bash -cd example -npm i # or yarn to install dependencies -npm start # or yarn start -``` - -The default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, we use [Parcel's aliasing](https://parceljs.org/module_resolution.html#aliases). - -To do a one-off build, use `npm run build` or `yarn build`. - -To run tests, use `npm test` or `yarn test`. +## Usage -## Configuration +The API is very close to `useReducer`, except that: -Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly. +- The state reducer returns `[State, Effect[]]` instead of `State` +- You need to pass an effect reducer -### Jest +```typescript +import {useBireducer} from "react-use-bireducer"; -Jest tests are set up to run with `npm test` or `yarn test`. +declare function stateReducer(state: State, action: Action): [State, Effect[]]; +declare function effectReducer(effect: Effect): EffectCleanup | void; -### Bundle analysis - -Calculates the real cost of your library using [size-limit](https://github.com/ai/size-limit) with `npm run size` and visulize it with `npm run analyze`. - -#### Setup Files - -This is the folder structure we set up for you: - -```txt -/example - index.html - index.tsx # test your component here in a demo app - package.json - tsconfig.json -/src - index.tsx # EDIT THIS -/test - blah.test.tsx # EDIT THIS -.gitignore -package.json -README.md # EDIT THIS -tsconfig.json +const [state, dispatch] = useBireducer(stateReducer, effectReducer, defaultState); ``` -#### React Testing Library - -We do not set up `react-testing-library` for you yet, we welcome contributions and documentation on this. - -### Rollup - -TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details. - -### TypeScript - -`tsconfig.json` is set up to interpret `dom` and `esnext` types, as well as `react` for `jsx`. Adjust according to your needs. - -## Continuous Integration +See a complete [live example on +CodeSandbox](https://codesandbox.io/s/react-use-bireducer-example-20n30w?file=/src/App.tsx). -### GitHub Actions +## Development -Two actions are added by default: +Development environment is managed by [Nix](https://nixos.org/). First +you need to install it: -- `main` which installs deps w/ cache, lints, tests, and builds on all pushes against a Node and OS matrix -- `size` which comments cost comparison of your library on every pull request using [`size-limit`](https://github.com/ai/size-limit) - -## Optimizations - -Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations: - -```js -// ./types/index.d.ts -declare var __DEV__: boolean; - -// inside your code... -if (__DEV__) { - console.log('foo'); -} +```bash +curl -L https://nixos.org/nix/install | sh ``` -You can also choose to install and use [invariant](https://github.com/palmerhq/tsdx#invariant) and [warning](https://github.com/palmerhq/tsdx#warning) functions. - -## Module Formats - -CJS, ESModules, and UMD module formats are supported. - -The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found. - -## Deploying the Example Playground - -The Playground is just a simple [Parcel](https://parceljs.org) app, you can deploy it anywhere you would normally deploy that. Here are some guidelines for **manually** deploying with the Netlify CLI (`npm i -g netlify-cli`): +Then you can start your development environment by spawning a Nix +shell: ```bash -cd example # if not already in the example folder -npm run build # builds to dist -netlify deploy # deploy the dist folder +nix-shell ``` -Alternatively, if you already have a git repo connected, you can set up continuous deployment with Netlify: +Now you should be able to clone the repo and install Node.js +dependencies: ```bash -netlify init -# build command: yarn build && cd example && yarn && yarn build -# directory to deploy: example/dist -# pick yes for netlify.toml +git clone https://github.com/soywod/react-use-bireducer.git +cd react-use-bireducer +yarn ``` -## Named Exports +You can leave the development environment either by killing your +terminal or by entering the command `exit`. -Per Palmer Group guidelines, [always use named exports.](https://github.com/palmerhq/typescript#exports) Code split inside your React app instead of your React library. +## Tests -## Including Styles +Tests are handled by [Jest](https://jestjs.io/) (`.test` files) and +[React Testing +Library](https://testing-library.com/docs/react-testing-library/intro/) +(`.spec` files). -There are many ways to ship styles, including with CSS-in-JS. TSDX has no opinion on this, configure how you like. - -For vanilla CSS, you can include it at the root directory and add it to the `files` section in your `package.json`, so that it can be imported separately by your users and run through their bundler's loader. - -## Publishing to NPM - -We recommend using [np](https://github.com/sindresorhus/np). - -## Usage with Lerna - -When creating a new package with TSDX within a project set up with Lerna, you might encounter a `Cannot resolve dependency` error when trying to run the `example` project. To fix that you will need to make changes to the `package.json` file _inside the `example` directory_. - -The problem is that due to the nature of how dependencies are installed in Lerna projects, the aliases in the example project's `package.json` might not point to the right place, as those dependencies might have been installed in the root of your Lerna project. - -Change the `alias` to point to where those packages are actually installed. This depends on the directory structure of your Lerna project, so the actual path might be different from the diff below. - -```diff - "alias": { -- "react": "../node_modules/react", -- "react-dom": "../node_modules/react-dom" -+ "react": "../../../node_modules/react", -+ "react-dom": "../../../node_modules/react-dom" - }, +```bash +yarn test ``` -An alternative to fixing this problem would be to remove aliases altogether and define the dependencies referenced as aliases as dev dependencies instead. [However, that might cause other problems.](https://github.com/palmerhq/tsdx/issues/64) +## Sponsoring + +[![github](https://img.shields.io/badge/-GitHub%20Sponsors-fafbfc?logo=GitHub%20Sponsors&style=flat-square)](https://github.com/sponsors/soywod) +[![paypal](https://img.shields.io/badge/-PayPal-0079c1?logo=PayPal&logoColor=ffffff&style=flat-square)](https://www.paypal.com/paypalme/soywod) +[![ko-fi](https://img.shields.io/badge/-Ko--fi-ff5e5a?logo=Ko-fi&logoColor=ffffff&style=flat-square)](https://ko-fi.com/soywod) +[![buy-me-a-coffee](https://img.shields.io/badge/-Buy%20Me%20a%20Coffee-ffdd00?logo=Buy%20Me%20A%20Coffee&logoColor=000000&style=flat-square)](https://www.buymeacoffee.com/soywod) +[![liberapay](https://img.shields.io/badge/-Liberapay-f6c915?logo=Liberapay&logoColor=222222&style=flat-square)](https://liberapay.com/soywod) diff --git a/package.json b/package.json index 95abdde..cbc53a5 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,16 @@ "name": "react-use-bireducer", "author": "soywod ", "description": "React hook for managing effects within reducers.", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", - "source": "src/index.ts", - "exports": { - "require": "dist/index.cjs", - "default": "dist/index.modern.js" - }, - "main": "dist/index.js", - "module": "dist/index.esm.js", - "unpkg": "dist/index.umd.js", - "typings": "dist/index.d.ts", + "source": "./src/index.ts", + "exports": "./dist/index.mjs", + "main": "./dist/index.js", + "module": "./dist/index.esm.js", + "unpkg": "./dist/index.umd.js", + "typings": "./dist/index.d.ts", "files": [ - "dist" + "./dist" ], "devDependencies": { "@jest/types": "^28.1.0", @@ -34,6 +31,7 @@ "eslint-plugin-sort-keys-fix": "^1.1.2", "eslint-plugin-unused-imports": "^2.0.0", "husky": "^8.0.1", + "jest": "^28.1.0", "jest-environment-jsdom": "^28.1.0", "lint-staged": ">=10", "microbundle": "^0.15.0", @@ -57,8 +55,5 @@ "build": "microbundle", "test": "yarn jest", "lint": "yarn eslint --ext ts src" - }, - "dependencies": { - "jest": "^28.1.0" } } diff --git a/src/index.spec.tsx b/src/index.spec.tsx index 361cfea..111341b 100644 --- a/src/index.spec.tsx +++ b/src/index.spec.tsx @@ -8,17 +8,26 @@ type State = { count: number; }; -type Action = {type: "increment"; value: number} | {type: "decrement"; value: number} | {type: "reset"}; +type Action = + | {type: "increment"; value: number} + | {type: "decrement"; value: number} + | {type: "reset"}; type Effect = {type: "log"; value: string} | {type: "backup"; count: number}; const stateReducer: StateReducer = (state, action) => { switch (action.type) { case "increment": { - return [{count: state.count + action.value}, [{type: "log", value: `increment counter +${action.value}`}]]; + return [ + {count: state.count + action.value}, + [{type: "log", value: `increment counter +${action.value}`}], + ]; } case "decrement": { - return [{count: state.count - action.value}, [{type: "log", value: `decrement counter -${action.value}`}]]; + return [ + {count: state.count - action.value}, + [{type: "log", value: `decrement counter -${action.value}`}], + ]; } case "reset": { return [