React useState - setValue повторно отображает компонент, даже если значение совпадает - PullRequest
0 голосов
/ 20 февраля 2019

Я использую useState хук в пользовательском хуке.

Я вызываю функцию setValue, которая возвращается из useState дважды:

1) Послесобытие onChange

2) После того, как компонент был уведомлен об изменении с сервера.

Поток событий:

  • Событие onChange (в компоненте) триггеры setValue = rerender
  • Я использую хук useEffect ( = после rerender ) для обновления сервера изменений - функция APIвызван для обновления сервера
  • У меня есть специальная служба, которая получает ответ сервера и уведомляет компонент
  • При получении уведомления компонент снова вызывает setValue, но в этом случае значение остается тем жепоэтому не нужно перерисовывать.

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

Мой код:

Компонент усиления

import * as React from 'react';
import { useDSPParamUpdate } from '../../../Hooks/useDSPParamUpdate';
import { ControlParamProps } from '../..';

const Gain = (props: ControlParamProps) => {

  let min: number = 0;
  let max: number = 0;


  const { paramId, controlId } = props;
  const { param, value, setValue } = useDSPParamUpdate({ controlId, paramId })

  if (param && param.range && param.range.length >= 2) {
    min = param.range[0];
    max = param.range[1];
  }

  /*calls the setValue from the hook*/
  const handleChange = (event: any) => {
    const newValue = event.target.value;
    setValue(newValue);
  }


  return (
    <div className="gain">
      {max}
      <input className="dsp-action range-vertical" type="range"
        min={min}
        max={max}
        value={value}
        onChange={handleChange} />
      {min}
    </div>
  );
}

export default Gain;

useDSPParamUpdate - пользовательский hоок

    import * as React from 'react';
        import { ControlParamProps } from '../dsp';
        import { dspService } from '../../core/services/dsp.service';

        export function useDSPParamUpdate(props: ControlParamProps) {

            const initValue = ...
            const [value, setValue] = React.useState(initValue);

            function updateDevice() {
                // calls some API func to update the server (sends the value)
            }

            // subscribes to server changes
            React.useEffect(() => {
                    // subscribrs to server notifications
                    let unsubscribe = dspService.subscribe((newVal) => setValue(newVal));
                return () => {
                    unsubscribe();
                };
            }, []);


            // sends data to the server after update
            React.useEffect(() => {
                updateDevice();
            }, [value]);

            return { param, value, setValue };
        }

1 Ответ

0 голосов
/ 20 февраля 2019

Обычно это не проблема, если render() вызывается как дополнительное время.

Но если вы хотите, вы можете защитить setValue(), проверяя, является ли значение тем же

let unsubscribe = dspService.subscribe(
    (newVal) => 
        newVal !== value && setValue(newVal)
);  

Может быть, немного многословно, но это тот же подход, который обычно используется в componentDidUpdate

Обратите внимание, что useState не предоставляет никакой логики, как shouldComponentUpdate.Поэтому, если вы хотите сделать это более декларативным способом, вы должны реорганизовать свой компонент, чтобы получить доступ к классам PureComponent.

...