UNPKG

5.6 kBMarkdownView Raw
1# UID
2
3[![Build Status](https://travis-ci.org/thearnica/react-uid.svg?branch=master)](https://travis-ci.org/thearnica/react-uid)
4[![coverage-badge](https://img.shields.io/codecov/c/github/thearnica/react-uid.svg?style=flat-square)](https://codecov.io/github/thearnica/react-uid)
5[![NPM version](https://img.shields.io/npm/v/react-uid.svg)](https://www.npmjs.com/package/react-uid)
6[![Greenkeeper badge](https://badges.greenkeeper.io/thearnica/react-uid.svg)](https://greenkeeper.io/)
7[![bundle size](https://badgen.net/bundlephobia/minzip/react-uid)](https://bundlephobia.com/result?p=react-uid)
8[![downloads](https://badgen.net/npm/dm/react-uid)](https://www.npmtrends.com/react-uid)
9
10To generate a _stable_ UID/Key for a given `item`, consistently between client and server, **in 900 bytes**.
11
12⚠️ SSR: **Not compatible with Strict or Concurent mode**. Consider using _native_ `useId`(React 18) hook instead.
13
14> If your clientside is using StrictMode it will never match SSR-ed Ids due to double invocation
15
16Example - https://codesandbox.io/s/kkmwr6vv47
17
18## API
19
20React UID provides 3 different APIs
21
22- vanilla js API - `uid(item) -> key`
23- React Component, via renderProp based API - `<UID>{ id => <><label htmlFor={id}/><input id={id}/></>}</UID>`
24- React Hooks - `useUID`
25
26#### Javascript
27
28- `uid(item, [index])` - generates UID for an object(array, function and so on), result could be used as React `key`.
29 `item` should be an object, but could be anything. In case it is not an "object", and might have non-unique value - you have to specify second argument - `index`
30
31```js
32import { uid } from 'react-uid';
33
34// objects
35const data = [{ a: 1 }, { b: 2 }];
36data.map((item) => <li key={uid(item)}>{item}</li>);
37
38// unique strings
39const data = ['a', 'b'];
40data.map((item) => <li key={uid(item)}>{item}</li>);
41
42// strings
43const data = ['a', 'a'];
44data.map((item, index) => <li key={uid(item, index)}>{item}</li>);
45```
46
47JS API might be NOT (multi-tenant)**SSR friendly**,
48
49#### React Components
50
51- (deprecated)`UID` - renderless container for generation Ids
52- `UIDConsumer` - renderless container for generation Ids
53
54```js
55 import {UID} from 'react-uid';
56
57 <UID>
58 {id => (
59 <Fragment>
60 <input id={id} />
61 <label htmlFor={id} />
62 </Fragment>
63 )}
64 </UID>
65
66 // you can apply some "naming conventions" to the keys
67 <UID name={ id => `unique-${id}` }>
68 {id => (
69 <Fragment>
70 <input id={id} />
71 <label htmlFor={id} />
72 </Fragment>
73 )}
74 </UID>
75
76 // UID also provide `uid` as a second argument
77 <UID>
78 {(_, uid) => (
79 data.map( item => <li key={uid(item)}>{item}</li>)
80 )}
81 </UID>
82
83 // in the case `item` is not an object, but number or string - provide and index
84 <UID>
85 {(_, uid) => (
86 data.map( (item, index) => <li key={uid(item, index)}>{item}</li>)
87 )}
88 </UID>
89```
90
91The difference between `uid` and `UID` versions are in "nesting" - any `UID` used inside another `UID` would contain "parent prefix" in the result, scoping `uid` to the local tree branch.
92
93UID might be NOT **SSR friendly**,
94
95#### Hooks (16.8+)
96
97- `useUID()` will generate a "stable" UID
98- `useUIDSeed()` will generate a seed generator, you can use for multiple fields
99
100```js
101import { useUID, useUIDSeed } from 'react-uid';
102
103const Form = () => {
104 const uid = useUID();
105 return (
106 <>
107 <label htmlFor={uid}>Email: </label>
108 <input id={uid} name="email" />
109 </>
110 )
111}
112
113const Form = () => {
114 const seed = useUIDSeed();
115 return (
116 <>
117 <label htmlFor={seed('email')}>Email: </label>
118 <input id={seed('email')} name="email" />
119 {data.map(item => <div key={seed(item)}>...</div>
120 </>
121 )
122}
123```
124
125Hooks API **is SSR friendly**,
126
127### Server-side friendly UID
128
129- `UIDReset`, `UIDConsumer`, `UIDFork` - SSR friendly UID. Could maintain consistency across renders.
130 They are much more complex than `UID`, and provide functionality you might not need.
131
132The key difference - they are not using global "singlentone" to track used IDs,
133but read it from Context API, thus works without side effects.
134
135Next example will generate the same code, regardless how many time you will render it
136
137```js
138import { UIDReset, UIDConsumer } from 'react-uid';
139
140<UIDReset>
141 <UIDConsumer>
142 {(id, uid) => (
143 <Fragment>
144 <input id={id} />
145 <label htmlFor={id} />
146 data.map( item => <li key={uid(item)}>{item}</li>)
147 </Fragment>
148 )}
149 </UIDConsumer>
150</UIDReset>;
151```
152
153**UID** is not 100% SSR friendly - use **UIDConsumer**.
154
155### Code splitting
156
157Codesplitting may affect the order or existence of the components, so alter
158the `componentDidMount` order, and change the generated ID as result.
159
160In case of SPA, this is not something you should be bothered about, but for SSR
161this could be fatal.
162
163Next example will generate consistent keys regardless of component mount order.
164Each call to `UIDFork` creates a new branch of UIDs untangled from siblings.
165
166```js
167import {UIDReset, UIDFork, UIDConsumer} from 'react-uid';
168
169 <UIDReset>
170 <UIDFork>
171 <AsyncLoadedCompoent>
172 <UIDConsumer>
173 { uid => <span>{uid} is unique </span>}
174 </UIDConsumer>
175 </UIDFork>
176 <UIDFork>
177 <AsyncLoadedCompoent>
178 <UIDConsumer>
179 { uid => <span>{uid} is unique </span>}
180 </UIDConsumer>
181 </UIDFork>
182 </UIDReset>
183```
184
185The hooks API only needs the `<UIDFork>` wrapper.
186
187### So hard?
188
189"Basic API" is not using Context API to keep realization simple, and React tree more flat.
190
191# Types
192
193Written in TypeScript
194
195# Licence
196
197MIT