Как я могу глубоко сравнивать объекты / массивы в useEffect / React?

#arrays #reactjs #object #react-hooks

#массивы #reactjs #объект #реагирующие хуки

Вопрос:

Я просто хотел знать, как я могу глубоко сравнивать объекты / массивы в useEffect или реагировать, чтобы сделать это уже под капотом? Я пытаюсь заставить его работать таким же образом и для версии hook.

В предыдущей версии я делал, как показано ниже;

 componentWillReceiveProps(nextProps){
   const { settings: { config = {} } = {}, pluginData = [] } = this.props
   const { settings: { config: nextConfig = {} } = {}, pluginData: nextPluginData = [] } = nextProps

   if(!_.isEqual(config, nextConfig) amp;amp; !_.isEqual(pluginData, nextPluginData )){
        //do sth with new props
   }
}
 

Для следующей версии;

 useEffect(() => {
 // do sth with new props
}, [props.settings.config, props.pluginData])
 

Как вы видите, я использовал isEqual от Lodash для сравнения, является ли это тем же объектом / массивом или нет. Как это сделать в хуках? Как реагирует сравнение, когда я передаю вложенные объекты / массивы в массив зависимостей useEffect? Выполняет ли это глубокое сравнение или поверхностное?

А также;

Что мне делать, если я не уверен, что у реквизита есть настройки и конфигурация в предыдущей версии, я делал, как показано ниже;

 const { settings = {} } = nextProps
 

Как это сделать в версии hook? Следует ли продолжать тот же подход?

PS: config является вложенным объектом и pluginData является массивом объектов.

//// ПОСЛЕ УТОЧНЕНИЯ ВОПРОСА

 UNSAFE_componentWillReceiveProps(nextProps) {
    const {
      settings: { config: { data: { enabled: nextEnabled = false } = {} } = {} } = {},
      pluginData: nextPluginData = []
    } = nextProps || {}

    if (nextEnabled) {
      if (nextPluginData[0]) {
        this.setState({ disabled: !nextPluginData[0][nextEnabled] })
      }
    }
  }
 

Я работаю над перезаписью одного из компонентов, который уже написан с помощью класса cmp. Как я могу преобразовать этот фрагмент кода из class cmp в hook cmp?

Комментарии:

1. props Поскольку они меняются в родительском компоненте, у них должна быть новая ссылка, и ваш дочерний компонент будет повторно отображен. Нет необходимости глубоко сравнивать их. Однако, если вы обосновываете этот вопрос ограничением количества повторных отправлений (что явно не указано), вам следует заглянуть в memo

2. Я действительно знаю, что они получают новую ссылку каждый раз, когда родительский рендеринг, но если вы используете Lodash isEqual и ваш объект не имеет внутри него функций (fn, созданных во время рендеринга), измененная ссылка не имеет значения. Он будет сравниваться, как ожидалось, и получит true, когда это произойдет. Я хочу сказать, что получает новое значение из реквизита, если оно действительно меняется.

3. Возможно, вы недостаточно ясно объяснили пример использования. Vivere правильно. Вам не нужно или не нужно выполнять глубокое равенство, поскольку вы можете просто использовать глубокую зависимость, как вы это делали, и когда это значение изменилось по сравнению с предыдущим рендерингом, запустите обратный вызов эффекта. Является ли проблема «равенства» больше связанной с массивом?

Ответ №1:

Основываясь на вашем комментарии, вы можете сделать что-то вроде этого:

 const [config, setConfig] = useState(undefined);
const [pluginData, setPluginData] = useState(undefined);

useEffect(() => {
    if(!_.isEqual(config, props.settings.config) amp;amp; !_.isEqual(pluginData, props.pluginData)) {
        //do sth with new props

        // Update old props to have them actual for the next comparison
        setConfig(props.settings.config);
        setPluginData(props.pluginData);
    }
}, [props.settings.config, props.pluginData])
 

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

Комментарии:

1. Отличный ответ. В вашем примере есть два сравнения, одно из которых очевидно равно тому, что вы сделали, а второе находится в зависимости [props.settings.config, props.pluginData] В чем различия между этими двумя сравнениями? Разве это не то же самое? Я имею в виду, не реагирует ли сравнение config и pluginData глубоко, когда мы используем useEffect с массивом зависимостей?