web-dev-qa-db-ja.com

Reactフックで次のレンダリングに何かを集中させる方法

私はフックで遊んでいて、次のことをしようとしています:

import React, { useState, useRef } from 'react';

const EditableField = () => {
  const [isEditing, setEditing] = useState(false);
  const inputRef = useRef();
  const toggleEditing = () => {
    setEditing(!isEditing);
    if (isEditing) {
      inputRef.current.focus();
    }
  };
  return (
    <>
      {isExpanded && <input ref={inputRef} />}
      <button onClick={toggleEditing}>Edit</button>
    </>
  );
};

コンポーネントはまだ再レンダリングされておらず、入力フィールドはまだレンダリングされていない(したがって、まだフォーカスできない)ため、currentはnullであるため、これは失敗します。

これを行う正しい方法は何ですか? React Hooks FAQ)で提案されている usePrevious フックを使用できますが、これは苦痛を伴う回避策のようです。

別の方法がありますか?

11
Kris Selbekk

useEffect フックを使用して、isEditingが変更されたときにレンダリングのたびに関数を実行できます。この関数では、isEditingtrueであるかどうかを確認し、入力にフォーカスできます。

const { useState, useRef, useEffect } = React;

const EditableField = () => {
  const [isEditing, setEditing] = useState(false);
  const toggleEditing = () => {
    setEditing(!isEditing);
  };

  const inputRef = useRef(null);

  useEffect(() => {
    if (isEditing) {
      inputRef.current.focus();
    }
  }, [isEditing]);
  
  return (
    <div>
      {isEditing && <input ref={inputRef} />}
      <button onClick={toggleEditing}>Edit</button>
    </div>
  );
};

ReactDOM.render(<EditableField />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
  
<div id="root"></div>
21
Tholle