Git Product home page Git Product logo

react-uid's Introduction

UID

Build Status coverage-badge NPM version Greenkeeper badge bundle size downloads

To generate a stable UID/Key for a given item, consistently between client and server, in 900 bytes.

⚠️ SSR: Not compatible with Strict or Concurent mode. Consider using native useId(React 18) hook instead.

If your clientside is using StrictMode it will never match SSR-ed Ids due to double invocation

Example - https://codesandbox.io/s/kkmwr6vv47

API

React UID provides 3 different APIs

  • vanilla js API - uid(item) -> key
  • React Component, via renderProp based API - <UID>{ id => <><label htmlFor={id}/><input id={id}/></>}</UID>
  • React Hooks - useUID

Javascript

  • uid(item, [index]) - generates UID for an object(array, function and so on), result could be used as React key. 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
import { uid } from 'react-uid';

// objects
const data = [{ a: 1 }, { b: 2 }];
data.map((item) => <li key={uid(item)}>{item}</li>);

// unique strings
const data = ['a', 'b'];
data.map((item) => <li key={uid(item)}>{item}</li>);

// strings
const data = ['a', 'a'];
data.map((item, index) => <li key={uid(item, index)}>{item}</li>);

JS API might be NOT (multi-tenant)SSR friendly,

React Components

  • (deprecated)UID - renderless container for generation Ids
  • UIDConsumer - renderless container for generation Ids
 import {UID} from 'react-uid';

 <UID>
     {id => (
       <Fragment>
         <input id={id} />
         <label htmlFor={id} />
       </Fragment>
     )}
 </UID>

 // you can apply some "naming conventions" to the keys
  <UID name={ id => `unique-${id}` }>
      {id => (
        <Fragment>
          <input id={id} />
          <label htmlFor={id} />
        </Fragment>
      )}
  </UID>

  // UID also provide `uid` as a second argument
  <UID>
       {(_, uid) => (
         data.map( item => <li key={uid(item)}>{item}</li>)
       )}
  </UID>

  // in the case `item` is not an object, but number or string - provide and index
  <UID>
       {(_, uid) => (
         data.map( (item, index) => <li key={uid(item, index)}>{item}</li>)
       )}
  </UID>

The 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.

UID might be NOT SSR friendly,

Hooks (16.8+)

  • useUID() will generate a "stable" UID
  • useUIDSeed() will generate a seed generator, you can use for multiple fields
import { useUID, useUIDSeed } from 'react-uid';

const Form = () => {
  const uid = useUID();
  return (
    <>
     <label htmlFor={uid}>Email: </label>
     <input id={uid} name="email" />
    </>
  )
}

const Form = () => {
  const seed = useUIDSeed();
  return (
    <>
     <label htmlFor={seed('email')}>Email: </label>
     <input id={seed('email')} name="email" />
     {data.map(item => <div key={seed(item)}>...</div>
    </>
  )
}

Hooks API is SSR friendly,

Server-side friendly UID

  • UIDReset, UIDConsumer, UIDFork - SSR friendly UID. Could maintain consistency across renders. They are much more complex than UID, and provide functionality you might not need.

The key difference - they are not using global "singlentone" to track used IDs, but read it from Context API, thus works without side effects.

Next example will generate the same code, regardless how many time you will render it

import { UIDReset, UIDConsumer } from 'react-uid';

<UIDReset>
  <UIDConsumer>
    {(id, uid) => (
      <Fragment>
        <input id={id} />
        <label htmlFor={id} />
        data.map( item => <li key={uid(item)}>{item}</li>)
      </Fragment>
    )}
  </UIDConsumer>
</UIDReset>;

UID is not 100% SSR friendly - use UIDConsumer.

Code splitting

Codesplitting may affect the order or existence of the components, so alter the componentDidMount order, and change the generated ID as result.

In case of SPA, this is not something you should be bothered about, but for SSR this could be fatal.

Next example will generate consistent keys regardless of component mount order. Each call to UIDFork creates a new branch of UIDs untangled from siblings.

import {UIDReset, UIDFork, UIDConsumer} from 'react-uid';

 <UIDReset>
     <UIDFork>
      <AsyncLoadedCompoent>
         <UIDConsumer>
           { uid => <span>{uid} is unique </span>}
         </UIDConsumer>
     </UIDFork>
     <UIDFork>
       <AsyncLoadedCompoent>
          <UIDConsumer>
            { uid => <span>{uid} is unique </span>}
          </UIDConsumer>
      </UIDFork>
 </UIDReset>

The hooks API only needs the <UIDFork> wrapper.

So hard?

"Basic API" is not using Context API to keep realization simple, and React tree more flat.

Types

Written in TypeScript

Licence

MIT

react-uid's People

Contributors

dependabot[bot] avatar greenkeeper[bot] avatar jjclane avatar kumar303 avatar ptamarit avatar thearnica avatar thekashey avatar wmertens avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-uid's Issues

Produce CSS valid ids

Numeric IDs are great with HTML5 but not so with CSS which requires

Attribute values must be a valid CSS identifiers or String.

As I understand this modules code the UIDs are numeric, so I prefix them with a character

const uid = `s${useUID()}`;

To avoid errors like, '#2' is not a valid selector. Given the likely usage of this I think it would be nice if it produces CSS valid ids by default.

SSR issues with React Strict Mode

Firstly, thanks for this great little library!

I've been experimenting with enabling React Strict Mode on my project to discover potential bugs. One of the things Strict Mode does is to invoke lifecycle methods multiple times to find unexpected side effects. It looks like this only happens on the client side, and it has the unfortunate effect of incrementing each ID twice.

If we look at the example at https://codesandbox.io/s/kkmwr6vv47, it returns the following IDs:

top level (One) key:1-1
+ nested element 1: 1-2
+ nested element 2: 1-3-1
top level (Two) key:2-1
+ nested element 1: 2-2
+ nested element 2: 2-3-1
top level (Three) key:3-1
+ nested element 1: 3-2
+ nested element 2: 3-3-1

If we wrap that example in <React.StrictMode> (see https://codesandbox.io/s/react-uid-example-forked-ie935), we get:

top level (One) key:2-2
+ nested element 1: 2-4
+ nested element 2: 2-6-2
top level (Two) key:4-2
+ nested element 1: 4-4
+ nested element 2: 4-6-2
top level (Three) key:6-2
+ nested element 1: 6-4
+ nested element 2: 6-6-2

I'm not sure what the right fix is, but ideally strict mode shouldn't cause any observable changes to the output, since these may cause breakages in future versions of React (e.g., once they enable concurrent rendering by default).

Q: How to use a prefix

Is there a way to set a prefix for useUID hook?

I'm want to prefix some ids such as input-1, is the recommended approach just to append the string myself?

I think it would be useful if we could do something like useUID('input');

Build is not working correctly

export const UIDReset: React.FC<React.PropsWithChildren<WithPrefix>> = ({ children, prefix = '' }) => { const [valueSource] = useState(() => createSource(prefix)); return <source.Provider value={valueSource}>{children}</source.Provider>; };

This code is getting transpiling to

export var UIDReset = function (_a) { var children = _a.children, _b = _a.prefix, prefix = _b === void 0 ? '' : _b; var z = createSource(prefix); return (React.createElement(source.Provider, { value: z }, children)); };

Which is wrong because in this createSource is getting called on every rerender which leads to new reference of valueSource. Which causes rerendering of every component where we use this context.

Need to fix build process for this.

An in-range update of codecov is breaking the build 🚨


🚨 Reminder! Less than one month left to migrate your repositories over to Snyk before Greenkeeper says goodbye on June 3rd! πŸ’œ πŸššπŸ’¨ πŸ’š

Find out how to migrate to Snyk at greenkeeper.io


The devDependency codecov was updated from 3.6.5 to 3.7.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

codecov is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 11 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Hooks require 16.8 not 16.7

You docs, and even the checks on the code say that Hooks require 16.7+, but that's not true. React 16.8 contains hooks.

You're also using 16.7.0-alpha.2 in your devDependencies. You may want to bump that to the shipping/non-alpha version

An in-range update of react is breaking the build 🚨

There have been updates to the react monorepo:

    • The peerDependency react was updated from 16.6.1 to 16.6.2.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

This monorepo update includes releases of one or more dependencies which all belong to the react group definition.

react is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Support for React 18

Hey there, React 18 came out this week, and react-uid is on my list of dependencies that need to add support before I can upgrade.

It doesn't look like there are any obvious breaking changes that would affect react-uid, so adding support should be as simple as updating the peerDependencies.

Happy to PR the fix if I can get permissions :)

Array of uids

I want to make an accessible tabs component. In my case there are two loops for render tabs and panels. Please clarify how to assign ids of loop's item to each on other respectively using useUIDSeed (or another approach)? First thing that comes to mind is make two arrays of uids, but I'm not sure that is the right way.

tabs.map(tab =>
<Tab
    key={seed(tab)}
    id={seed(tab)}
    aria-controls={panel ID by index ??}
    role="tab"
>
...
panels.map(panel =>
<Panel
    key={seed(panel)}
    id={seed(panel)}
    role="tabpanel"
    aria-labelledby={tab ID by index ??}
/>

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.