Пользовательский крючок для текстового поля, кажется, не работает - PullRequest
0 голосов
/ 10 апреля 2019

Я пытался придумать пользовательский хук, чтобы сделать текстовое поле настраиваемым, то есть передать набор данных в пользовательский хук, который дал бы мне текстовое поле, которое нужно использовать.

Текстовое поле с использованием ловушки отображается так, как ожидалось, но я не понимаю, почему этот подход нарушает ввод, созданный с помощью настраиваемой ловушки. После каждого нажатия клавиши вход теряет фокус и не работает как другой вход, который использует useState напрямую. Было бы здорово, если бы кто-то мог объяснить, что происходит, а что я не смог понять.

App.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import useTextFieldBroken from "./useTextFieldBroken";

import "./styles.css";

function App() {
  const [notBrokenValue, notBrokenSetValue] = useState("");

  const [TextFieldBrokenInputOne] = useTextFieldBroken(
    "brokenOne",
    "Broken Input One",
    ""
  );

  const notBrokenOnChange = e => {
    notBrokenSetValue(e.target.value);
  };

  return (
    <div>
      <label htmlFor="notBroken">
        <h3>Not Broken Input</h3>
        <input
          id="notBroken"
          onChange={notBrokenOnChange}
          value={notBrokenValue}
        />
      </label>
      <TextFieldBrokenInputOne />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

customHook.js

import React, { useState } from "react";

const useTextFieldBroken = (id, label, initialValue = "") => {
  const [value, setValue] = useState(initialValue);

  const handleChange = e => {
    setValue(e.target.value);
  };

  const TextField = () => {
    console.log("Rendered the input field");
    return (
      <label htmlFor={id}>
        <h3>{label}</h3>
        <input
          type="text"
          name={id}
          id={id}
          onChange={handleChange}
          value={value}
        />
      </label>
    );
  };

  return [TextField, value, setValue];
};

export default useTextFieldBroken;

https://codesandbox.io/s/4xj382vj40

1 Ответ

1 голос
/ 10 апреля 2019

Ваш ввод теряет фокус, потому что вы полностью перерисовываете дерево, которое создает его при каждом изменении.

Хорошей новостью является то, что для этого вам не нужен хук, просто вместо этого переведите ваш хук в функциональный компонент:

App.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import TextFieldBroken from "./useTextFieldBroken";

import "./styles.css";

function App() {
  const [notBrokenValue, notBrokenSetValue] = useState("");

  const notBrokenOnChange = e => {
    notBrokenSetValue(e.target.value);
  };

  return (
    <div>
      <label htmlFor="notBroken">
        <h3>Not Broken Input</h3>
        <input
          id="notBroken"
          onChange={notBrokenOnChange}
          value={notBrokenValue}
        />
      </label>
      <TextFieldBroken label="Previously Broken" id="previously-broken" />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

customHook.js

import React, { useState } from "react";

const TextFieldBroken = ({ id, label, initialValue = "" }) => {
  const [value, setValue] = useState(initialValue);

  const handleChange = e => {
    setValue(e.target.value);
  };

  return (
    <label htmlFor={id}>
      <h3>{label}</h3>
      <input
        type="text"
        name={id}
        id={id}
        onChange={handleChange}
        value={value}
      />
    </label>
  );
};

export default TextFieldBroken;
...