代码之家  ›  专栏  ›  技术社区  ›  enoch

类组件到功能组件的工作方式不符合预期

  •  0
  • enoch  · 技术社区  · 4 年前

    我的实现在类组件上运行得很好,但是当我尝试将其转换为工作组件时,当我执行搜索时,返回数据,如果我执行了另一次搜索,则仍然显示来自上一次搜索的上一个数据

    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>
      );
    };
    
    0 回复  |  直到 4 年前
        1
  •  3
  •   Henry Mueller    4 年前

    对于功能组件,不能运行效果(如 getFilmsWithSearch )外部 useEffect .

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

    当你打电话的时候 _loadFilms onSubmitEditing={() => _searchFilms()} 事件处理程序,您没有在内部运行 ,不同于 _电影胶片 使用效果 与组件装载一起运行的(因为 [] ,它在挂载时运行一次)。

    要解决这个问题,您通常需要 _searchFilms 设置一个状态变量(类似 reloadRequested 使用效果

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

    要获得一个包含大量解释的更完整的示例,请尝试本文 https://www.robinwieruch.de/react-hooks-fetch-data .