Мне действительно нужен хук useEffect () здесь? - PullRequest
0 голосов
/ 05 февраля 2020

Как новичок React Native ie, я работаю над приложением для android. По сути, приложение позволяет пользователю фильтровать базу данных в соответствии с заданными c параметрами поиска.

Теперь я попытался преобразовать компонент класса в функциональный компонент. Компонент просто загружает предварительно заполненную (Realm-) базу данных, отображает панель поиска, ожидающую ввода пользователя, выполняет запрос базы данных в соответствии с вводом пользователя и показывает результат.

В «старой» версии настройка базы данных была выполнена во время componentDidMount(), теперь я подумал, что с помощью useEffect() Hook выполнит эту работу, поскольку он работает вместо componentDidMount(). Но я обнаружил, что все логи c (которые я на самом деле хотел поместить в крючок) "голые" без какого-либо крючка работают просто отлично.

Я так растерялся из-за этого поведения, так как я не Я не ожидал, что так будет. Конечно, я что-то пропустил. Поиск в Google, к сожалению, не дал ответов. Вы можете помочь мне? Ниже приведен код компонента, о котором я говорю, SearchBar.js Большое спасибо за вашу помощь!

import React, {useState} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {connect} from 'react-redux';
import {Header, Icon, Item, Input} from 'native-base';
import Realm from 'realm';
import fs from 'react-native-fs';
import {setInputValueSearchBar} from '../../../actions';

const SearchBar = props => {
  let [inputValue, setInputValue] = useState(null);

  const sendInputValueToReduxStore = text => {
    setInputValue(text);
    props.setInputValueSearchBar(text);
  };

  // from here on, I wanted to use useEffect() ...
  const dogsSchema = {
    name: 'realm',
    properties: {
      name: 'string?',
      color: 'string?',
    },
  };

  let realm = new Realm({
    path: fs.DocumentDirectoryPath + '/default.realm',
    schema: [dogsSchema],
    readOnly: true,
  });

  const dogs = realm.objects('realm');
  let resultArray = [];

  const databaseRequest = () => {
    const query = inputValue;
    const result = inputValue
      ? dogs.filtered("name == '" + query + "'")
      : 'default';
    resultArray = Array.from(result);
    return resultArray.map(dog => (
      <Text className="dog" key={dog.name}>
        {dog.name}
      </Text>
    ));
  };

  //... until here

  const isText = props.text;

  return (
    <View>
      <Header searchBar rounded>
        <Item>
          <Icon name="ios-search" />
          <Input
            placeholder="Search"
            onChangeText={text => sendInputValueToReduxStore(text)}
            value={inputValue}
          />
        </Item>
      </Header>
      <View>{databaseRequest()}</View>
    </View>
  );
};

function mapStateToProps(state) {
  return {
    inputValue: state.inputValue,
  };
}

const mapDispatchToProps = {
  setInputValueSearchBar,
};

export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);

Это тот же компонент, что и компонент класса перед рефакторингом:

import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {connect} from 'react-redux';
import {Header, Icon, Item, Input} from 'native-base';
import Realm from 'realm';
import fs from 'react-native-fs';
import {setInputValueSearchBar} from '../../../actions';

class SearchBar extends React.Component {
  state = {
    inputValue: null,
  };

  sendInputValueToReduxStore(text) {
    this.setState({inputValue: text});
    this.props.setInputValueSearchBar(text);
  }

  componentWillMount() {
    const dogsSchema = {
      name: 'realm',
      properties: {
        name: 'string?',
        color: 'string?',
      },
    };

    let realm = new Realm({
      path: fs.DocumentDirectoryPath + '/default.realm',
      schema: [dogsSchema],
      readOnly: true,
    });

    const dogs = realm.objects('realm');
    let resultArray = [];

    this.databaseRequest = () => {
      const query = this.state.inputValue;
      const result = this.state.inputValue
        ? dogs.filtered("name == '" + query + "'")
        : 'default';
      resultArray = Array.from(result);
      return resultArray.map(dog => (
        <Text className="dog" key={dog.name}>
          {dog.name}
        </Text>
      ));
    };
  }

  render() {
    const isText = this.props.text;
    return (
      <View>
        <Header searchBar rounded>
          <Item>
            <Icon name="ios-search" />
            <Input
              placeholder="Search"
              onChangeText={text => this.sendInputValueToReduxStore(text)}
              value={this.state.inputValue}
            />
          </Item>
        </Header>
        {isText && (
          <View>
            <Text>{this.props.text}</Text>
          </View>
        )}
        <View>{this.databaseRequest()}</View>
      </View>
    );
  }
}

function mapStateToProps(state) {
  return {
    inputValue: state.inputValue,
  };
}

const mapDispatchToProps = {
  setInputValueSearchBar,
};

export default withNavigation(
  connect(mapStateToProps, mapDispatchToProps)(SearchBar),
);

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

С точки зрения производительности, это не очень хороший подход.

Код выполняется при каждом рендеринге, поэтому каждый раз при изменении значения пропа или состояния, даже если он не связан с этим фрагментом кода.

Хук useEffect также выполняет каждый рендеринг, НО позволяет вам передать список зависимостей (или пустой список, если у него нет зависимостей, тогда он будет выполнен один раз). Тогда код будет выполняться только при изменении одной из зависимостей.

1 голос
/ 05 февраля 2020

Конечно, это будет работать без useEffect. Но это также будет происходить каждый раз, когда компонент будет перерисован. Это может не быть проблемой в вашем приложении по нескольким причинам:

  • Возможно, ваш компонент не часто рендерится повторно, в зависимости от того, в каком состоянии вы управляете / обновляете и где
  • Возможно, логика c - это тривиальная трата ресурсов, и неважно, часто ли она выполняется

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

Если он не вызывается постоянно (или, по крайней мере, не слишком часто), то вы, конечно, можете сохранить это так. Просто имейте в виду, что он может начать повторно вызываться постоянно на основе факторов вне этого компонента, всего, что может привести к повторному рендерингу этого компонента.

Если это , то это будет вызывается постоянно, тогда для этого useEffect. Вы можете выполнить эту логику c только при первой загрузке компонента, не имея зависимостей:

useEffect(() => {
  // your logic
}, []);

Или вы можете добавить зависимости, чтобы запускать эту логику c каждый раз, когда эти зависимости меняются. Например, возможно повторно вызвать его в любое время, когда ваши inputValue изменятся:

useEffect(() => {
  // your logic
}, [inputValue]);
...