[React] React hook, component props for refactoring

Idea is put component props inside hook, and return from hook, that's way to keep component clean and simple

 

Hook:

import { MachineOptions } from "./machine";
import { machine } from "./machine";
import { useMachine } from "@zag-js/react";
import { ComponentProps } from "react";

type LabelProps = ComponentProps<"label"> & { "data-part": "label" };
type InputProps = ComponentProps<"input"> & {
  "data-part": string;
};

export function usePinMachine(options: MachineOptions) {
  const [state, send] = useMachine(machine(options));
  const { value, name } = state.context;
  const valueAsString = value.join("");
  return {
    value,
    valueAsString,
    getLabelProps(): LabelProps {
      return {
        "data-part": "label",
        onClick() {
          send({ type: "LABEL_CLICK" });
        },
      };
    },
    getHiddenInput(): InputProps {
      return {
        "data-part": "hidden-input",
        type: "hidden",
        name,
        value: value.join(""),
      };
    },
    getInputProps({ index }: { index: number }): InputProps {
      return {
        "data-part": "input",
        value: value[index],
        maxLength: 2,
        onChange(event) {
          const { value } = event.target;
          send({ type: "INPUT", index, value });
        },
        onFocus() {
          send({ type: "FOCUS", index });
        },
        onBlur() {
          send({ type: "BLUR" });
        },
        onKeyDown(event) {
          const { key } = event;
          if (key === "Backspace") {
            send({ type: "BACKSPACE", index });
          }
        },
        onPaste(event) {
          event.preventDefault();
          const value = event.clipboardData.getData("Text").trim();
          send({ type: "PASTE", value, index });
        },
      };
    },
  };
}

 

Component:

import "./App.css";
import { usePinMachine } from "./use-pin-machine";

function App() {
  const { value, getLabelProps, getHiddenInput, getInputProps } = usePinMachine(
    {
      numOfFields: 4,
      name: "pincode",
      onCompleted(value) {
        console.log(value);
      },
    }
  );

  return (
    <div className="App">
      <form
        onSubmit={(event) => {
          event.preventDefault();
          const formData = new FormData(event.currentTarget);
        }}
      >
        <div data-part="container">
          <label {...getLabelProps()}>Enter verification</label>
          <input {...getHiddenInput()} />
          <div data-part="input-group">
            {value.map((_, index) => (
              <input key={index} {...getInputProps({ index })} />
            ))}
          </div>
        </div>
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

export default App;

 

posted @ 2023-02-19 03:23  Zhentiw  阅读(17)  评论(0编辑  收藏  举报