Обновлять реагирующий компонент только при нажатии кнопки с зацепками - PullRequest
1 голос
/ 04 марта 2020

Приложение :

  1. Панель поиска с двумя полями ввода текста (input1, input2)
  2. Три кнопки: SearchX, SearchY, Очистить результаты
  3. Оба поиска могут принимать input1 и input2 в качестве параметров для получения двух разных результатов.
  4. Есть компонент результата, который принимает и входные данные, действие и визуализирует компонент поиска в зависимости от действия.
function TestComponent() {
  const [input1, setInput1] = useState('');
  const [input2, setInput2] = useState('');
  const [action, setAction] = useState(null);

  const onInput1Change = evt => setInput1(evt.target.value);
  const onInput2Change = evt => setInput2(evt.target.value);

  return (
    <div>
      <input type="text" value={input1} onChange={onInput1Change} />
      <input type="text" value={input2} onChange={onInput2Change} />
      <button type="button" onClick={() => setAction('SearchX')}>
        SearchX
      </button>
      <button type="button" onClick={() => setAction('SearchY')}>
        SearchY
      </button>
      <button type="button" onClick={() => setAction('Clear results')}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

function ResultComponent({ input1, input2, action }) {
  if (action === 'SearchX') {
    return <SearchX input1={input1} input2={input2} />;
  }

  if (action === 'SearchY') {
    return <SearchY input1={input1} input2={input2} />;
  }

  if (action === 'Clear results') {
    return null;
  }

  return null;
}

function SearchX({ input1, input2 }) {
  const [result, setResult] = useState(null);

  useEffect(() => {
    // Fetch and process X-way to get the result. Using timeout to simulate that
    const id = window.setTimeout(() => setResult(`Search X result with inputs: ${input1}, ${input2}`), 3000);
    return () => window.clearInterval(id);
  }, [input1, input2]);

  return <div>{result}</div>;
}

function SearchY({ input1, input2 }) {
  const [result, setResult] = useState(null);

  useEffect(() => {
    // Fetch and process Y-way to get the result. Using timeout to simulate that
    const id = window.setTimeout(() => setResult(`Search Y result with inputs: ${input1}, ${input2}`), 3000);
    return () => window.clearInterval(id);
  }, [input1, input2]);

  return <div>{result}</div>;
}

ReactDOM.render(<TestComponent />, document.getElementById('root'));

Задача :

Мы хотим, чтобы поиск инициировал только при нажатии кнопки . С помощью приведенного ниже кода, после первого результата поиска, как только вы измените свой ввод, компонент результата, как и ожидалось, будет повторно визуализирован, поэтому поиск снова начнется без нажатия кнопки

Шаги для воспроизведения проблемы:

  1. Введите «input1» в первом текстовом поле
  2. Введите «input2» во втором текстовом поле
  3. Нажмите «SearchX»
  4. Через 3 секунды вы должны увидеть что-то вроде «Поиск X результата с помощью входов: input1, input2»
  5. Изменить любое из полей ввода. Не нужно нажимать ввод.
  6. Через 3 секунды результат изменится без нажатия кнопки

Возможная опция :

Планирование использования React .memo ловит, чтобы сравнить действие prop перед обновлением компонента результата. Действие реквизита может изменяться только при нажатии кнопки и, следовательно, может решить проблему.

Вопрос :

  1. Есть ли какой-либо другой способ (любые другие хуки и c.) чтобы решить проблему?
  2. Или есть какой-то другой процесс / дизайн, которому я могу следовать, чтобы избежать памятки?

Ответы [ 2 ]

1 голос
/ 04 марта 2020

При взаимодействии ввода вы можете сбросить действие обратно в ноль. Это очистит текущий результат и не вызовет «поиск».

function TestComponent() {
  const [input1, setInput1] = useState('');
  const [input2, setInput2] = useState('');
  const [action, setAction] = useState(null);

  const onInput1Change = evt => {
    setInput1(evt.target.value);
    setAction(null);
  };
  const onInput2Change = evt => {
    setInput2(evt.target.value)
    setAction(null);
  };

  return (
    <div>
      <input type="text" value={input1} onChange={onInput1Change} />
      <input type="text" value={input2} onChange={onInput2Change} />
      <button type="button" onClick={() => setAction('SearchX')}>
        SearchX
      </button>
      <button type="button" onClick={() => setAction('SearchY')}>
        SearchY
      </button>
      <button type="button" onClick={() => setAction(null)}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

РЕДАКТИРОВАТЬ Используйте html5 формы для сохранения ввода и задания действия при отправке. Когда входы взаимодействуют с входами в состоянии, они не обновляются до тех пор, пока форма не будет отправлена.

function TestComponent() {
  const [input1, setInput1] = useState("");
  const [input2, setInput2] = useState("");
  const [action, setAction] = useState(null);

  return (
    <div>
      <form
        id="searchX"
        onSubmit={e => {
          e.preventDefault();
          setInput1(e.target.inputX.value);
          setAction("SearchX");
        }}
      />
      <form
        id="searchY"
        onSubmit={e => {
          e.preventDefault();
          setInput2(e.target.inputY.value);
          setAction("SearchY");
        }}
      />

      <input id="inputX" form="searchX" type="text" />
      <input id="inputY" form="searchY" type="text" />

      <input form="searchX" type="submit" value="SearchX" />
      <input form="searchY" type="submit" value="SearchY" />
      <button type="button" onClick={() => setAction(null)}>
        Clear results
      </button>

      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

Edit amazing-cori-97g7e

Кроме того, установка «сброса результатов» Действие кнопки назад к null сохраняет условную проверку в ResultComponent, которая упрощается до:

function ResultComponent({ input1, input2, action }) {
  if (action === 'SearchX') {
    return <SearchX input1={input1} input2={input2} />;
  }

  if (action === 'SearchY') {
    return <SearchY input1={input1} input2={input2} />;
  }

  return null;
}
0 голосов
/ 04 марта 2020

Вы можете использовать ссылки на входы и обновлять состояние только при нажатии кнопки.

export default function TestComponent() {
  const [input1, setInput1] = useState("");
  const [input2, setInput2] = useState("");
  const [action, setAction] = useState(null);

  const input1Ref = useRef(null);
  const input2Ref = useRef(null);

  const onButtonClick = () => {
    if (input1Ref.current) {
      setInput1(input1Ref.current.value);
    }
    if (input2Ref.current) {
      setInput2(input2Ref.current.value);
    }
  };

  const onSearchXClick = () => {
    onButtonClick();
    setAction("SearchX");
  };

  const onSearchYClick = () => {
    onButtonClick();
    setAction("SearchX");
  };

  return (
    <div>
      <input ref={input1Ref} type="text" />
      <input ref={input2Ref} type="text" />
      <button type="button" onClick={onSearchXClick}>
        SearchX
      </button>
      <button type="button" onClick={onSearchYClick}>
        SearchY
      </button>
      <button type="button" onClick={() => setAction("Clear results")}>
        Clear results
      </button>
      <ResultComponent input1={input1} input2={input2} action={action} />
    </div>
  );
}

Edit silly-maxwell-usrrj

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...