【问题标题】:Class component to functional component is not working as expected类组件到功能组件未按预期工作
【发布时间】:2020-08-30 01:40:54
【问题描述】:

我正在使用 react-native 实现无限滚动,当我进行搜索时会返回结果,如果结果在 API 上有很多页面,当我滚动 API 时会返回更多数据。

我的实现在类组件上运行良好,但是当我尝试将其转换为工作组件时,当我进行搜索时,将返回数据,如果我进行另一次搜索,仍会显示上一次搜索中的先前数据

类组件

class Exemple extends React.Component {
  constructor(props) {
    super(props);
    this.searchedText = "";
    this.page = 0;
    this.totalPages = 0;
    this.state = {
      films: [],
      isLoading: false,
    };
  }

  _loadFilms() {
    if (this.searchedText.length > 0) {
      this.setState({ isLoading: true });
      getFilmsWithSearch(this.searchedText, this.page + 1).then((data) => {
        this.page = data.page;
        this.totalPages = data.total_pages;
        this.setState({
          films: [...this.state.films, ...data.results],
          isLoading: false,
        });
      });
    }
  }
  
  _searchTextInputChanged(text) {
    this.searchedText = text;
  }

  _searchFilms() {
    this.page = 0;
    this.totalPages = 0;
    this.setState(
      {
        films: [],
      },
      () => {
        this._loadFilms();
      }
    );
  }

  _displayLoading() {
    if (this.state.isLoading) {
      return (
        <View style={styles.loading_container}>
          <ActivityIndicator size="large" />
        </View>
      );
    }
  }

  render() {
    return (
      <View style={styles.main_container}>
        <TextInput
          style={styles.textinput}
          placeholder="Titre du film"
          onChangeText={(text) => this._searchTextInputChanged(text)}
          onSubmitEditing={() => this._searchFilms()}
        />
        <Button title="Rechercher" onPress={() => this._searchFilms()} />
        <FlatList
          data={this.state.films}
          keyExtractor={(item, index) => index.toString()}
          renderItem={({ item }) => <FilmItem film={item} />}
          onEndReachedThreshold={0.5}
          onEndReached={() => {
            if (this.page < this.totalPages) {
              this._loadFilms();
            }
          }}
        />
        {this._displayLoading()}
      </View>
    );
  }
}

功能组件

const Search = () => {
  const [films, setFilms] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [page, setPage] = useState(0);
  const [totalPages, setTotalPages] = useState(0);
  const [searchedText, setSearchedText] = useState("");

  const _loadFilms = () => {
    if (searchedText.length > 0) {
      setIsLoading(true);
      getFilmsWithSearch(searchedText, page + 1).then((data) => {
        setPage(data.page);
        setTotalPages(data.total_pages);
        setFilms([...films, ...data.results]);
        setIsLoading(false);
      });
    }
  };

  useEffect(() => {
    _loadFilms();
  }, []);

  const _searchTextInputChanged = (text) => {
    setSearchedText(text);
  };

  const _searchFilms = () => {
    setPage(0);
    setTotalPages(0);
    setFilms([]);
    _loadFilms();
  };

  const _displayLoading = () => {
    if (isLoading) {
      return (
        <View style={styles.loading_container}>
          <ActivityIndicator size="large" />
        </View>
      );
    }
  };

  return (
    <View style={styles.main_container}>
      <TextInput
        style={styles.textinput}
        placeholder="Titre du film"
        onChangeText={(text) => _searchTextInputChanged(text)}
        onSubmitEditing={() => _searchFilms()}
      />
      <Button title="Rechercher" onPress={() => _searchFilms()} />
      <FlatList
        data={films}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({ item }) => <FilmItem film={item} />}
        onEndReachedThreshold={0.5}
        onEndReached={() => {
          if (page < totalPages) {
            _loadFilms();
          }
        }}
      />
      {_displayLoading()}
    </View>
  );
};

【问题讨论】:

  • 只是一个猜测,也许你已经看过这个了;但也许看看你是如何使用useEffect 的,因为它在每次组件状态更新并且你调用 loadfilms 时都会运行,它会保留现有的电影并添加新的电影。在_searchFilms函数中调用setFilms([])检查电影数组是否为空后,检查电影的状态。
  • @JakeB。我已经检查过它是否正常工作,但我必须在按钮上单击 2 次,就像这样 if (films.length === 0) { _loadFilms(); }

标签: javascript reactjs react-native react-native-flatlist


【解决方案1】:

使用功能组件,您无法在useEffect 之外运行效果(如getFilmsWithSearch)。

来自https://reactjs.org/docs/hooks-reference.html#useeffect

函数组件的主体(称为 React 的渲染阶段)中不允许使用突变、订阅、计时器、日志记录和其他副作用。这样做会导致 UI 中出现令人困惑的错误和不一致。

当您从onSubmitEditing={() =&gt; _searchFilms()} 事件处理程序内部调用_loadFilms 时,您没有在useEffect 内部运行,这与从useEffect_loadFilms 的调用不同,它与组件安装一起运行(因为第二个参数到useEffect[],它在装载时运行一次)。

要解决此问题,您通常会让_searchFilms 设置一个状态变量(类似于reloadRequested,但它不必是布尔值,请参阅下面的文章以获得不同的风格)并拥有第二个@ 987654334@ 类似这样的:

  useEffect(() => {
    if (reloadRequested) {
      _loadFilms();
      setReloadRequested(false);
    }
  }
, [reloadRequested])

如需了解更多解释的更完整示例,请尝试这篇文章https://www.robinwieruch.de/react-hooks-fetch-data

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多