GithubHelp home page GithubHelp logo

krassnig / use-destructuring Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 1.0 29 KB

useDestructuring() generates matching setState function for each property in a Javascript object.

Home Page: https://www.npmjs.com/package/use-destructuring

TypeScript 100.00%
destructuring form hook react setstate forms reactjs two-way-binding

use-destructuring's Introduction

useDestructuring

When calling useDestructuring matching setState function for each property in an object are created. The primary use case of useDestructuring is for simplifying forms in React.

import { useState } from "react";
import useDestructuring from "use-destructuring";

interface Person {
    firstName: string;
    lastName: string;
}

export const PersonForm: React.FC = () => {
    
    const [person, setPerson] = useState<Person>({ firstName: 'John', lastName: 'Smith' });

    const { firstName, lastName } = person; // Javascript object destructuring
    const { setFirstName, setLastName } = useDestructuring(person, setPerson);

    return (
        <form>
            <input type="text" value={firstName} onChange={e => setFirstName(e.target.value)} />
            <input type="text" value={lastName} onChange={e => setLastName(e.target.value)} />
        </form>
    );
};

Getting Started

First install use-destructuring using NPM

npm install use-destructuring

or if you are using Yarn

yarn add use-destructuring

then import it inside your React project

import useDestructuring from "use-destructuring";

Using Destructuring for Abstraction

Although the first example can easily be implemented without using useDestructuring, once your forms grow in complexity useDestructuring allows you to easily abstract form components in multiple ways.

import { useState } from "react";
import useDestructuring from "use-destructuring";

interface Person {
    firstName: string;
    lastName: string;
}

type Props = {
    person: Person;
    setPerson: React.Dispatch<React.SetStateAction<Person>>;
}

export const PersonForm: React.FC<Props> = ({ person, setPerson }) => {

    const { firstName, lastName } = person; // Javascript object destructuring
    const { setFirstName, setLastName } = useDestructuring(person, setPerson);

    return (
        <Form>
            <TextInput text={firstName} setText={setFirstName} />
            <TextInput text={lastName} setText={setLastName} />
        </Form>
    );
};

type TextInputProps = {
    text: string,
    setText: React.Dispatch<React.SetStateAction<string>>
}
const TextInput: React.FC<TextInputProps> = ({ text, setText }) => {
    return (<input type="text" value={text} onChange={e => setText(e.target.value)} />);
};

The PersonForm itself can easily become a reusable component that lets you freely move the Person state among its parent components. At the same time, it allows the implementation of form fields that need not know about the structure of the Person object.

Arrays

useDestructuring also supports destructuring of arrays. For example, our Person object from before might contain a list of telephone numbers. Simply extend the PersonForm like you would any other property. In this example the list of phone numbers is handled in a separate component.

PersonForm.tsx

interface Person {
    firstName: string;
    lastName: string;
    phoneNumbers: string[];
}

export const PersonForm: React.FC<Props> = ({ person, setPerson }) => {

    const { firstName, lastName, phoneNumbers } = person;
    const { setFirstName, setLastName, setPhoneNumbers } = useDestructuring(person, setPerson);

    return (
        <Form>
            <TextInput text={firstName} setText={setFirstName} />
            <TextInput text={lastName} setText={setLastName} />
            <PhoneNumbersInput phoneNumbers={phoneNumbers} setPhoneNumbers={setPhoneNumbers} />
        </Form>
    );
};

In the PhoneNumbersInput component call useDestructuring to get a list of tuples destructuredPhoneNumbers in which each tuple contains one entry of [phoneNumber, setPhoneNumber, removePhoneNumber]. The first value is just the value in the phoneNumbers[i] array itself, the second is a SetState function that overwrites that array element at index i and the third removes the element at position i from the array.

PhoneNumbersInput.tsx

type Props = {
    phoneNumbers: string[];
    setPhoneNumbers: React.Dispatch<React.SetState<string[]>>;
}

export const PhoneNumbersInput: React.FC<Props> = ({ phoneNumbers, setPhoneNumbers }) => {

    const destructuredPhoneNumbers = useDestructuring(phoneNumbers, setPhoneNumbers);

    return (
        <fieldset>
            { destructuredPhoneNumbers.map(([phoneNumber, setPhoneNumber, removePhoneNumber]) => (
                <span key={phoneNumber}>
                    <TextInput text={phoneNumber} setPhoneNumber={setPhoneNumber} >
                    <button type="button" onClick={() => removePhoneNumber()}>X</button>
                </span>
            )) }
            <button type="button" onClick={
                () => setPhoneNumbers(oldPhoneNumbers => [...oldPhoneNumbers, '+01234567'])
            }>Add New Telephone Number</button>
        </fieldset>
    );
}

To add additional phone numbers to the list of existing phone numbers, you can just use the setPhoneNumbers function which is already present.

Performance

Per default React will rerender the entire form and ALL its child components if some property of the form component state is changed. To only rerender components which have their props changed React components can be wrapped in React.memo calls. To support the usage of React.memo, useDestructuring saves all its produced setter functions so that they do not change from one rerender to the next, much like useState (but not exactly). That means that in the ideal scenario only the leaf component that is edited and all its parents up until the component that holds the form state are rerendered. Rerender counts can be reduced further by implementing a debounce in leaf fields that do not immidiately call setState (e.g. wait while the user is typing).

use-destructuring's People

Contributors

krassnig avatar

Watchers

 avatar

Forkers

nikkasyan

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.