Class 组件到功能组件未按预期工作
Class component to functional component is not working as expected
我正在使用 react-native 实现无限滚动,当我进行搜索时返回结果,如果结果在 API 上有很多页面,当我滚动 API returns 更多数据 .
我的实现在 class 组件上运行良好,但是当我尝试将其转换为工作组件时,当我进行搜索时,会返回数据,如果我进行另一次搜索,则会返回之前的数据仍然显示之前的搜索
class 组件
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
之外 运行 效果(例如 getFilmsWithSearch
)。
来自https://reactjs.org/docs/hooks-reference.html#useeffect
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
当您从 onSubmitEditing={() => _searchFilms()}
事件处理程序中调用 _loadFilms
时,您不在 useEffect
中 运行,这与对 _loadFilms
的调用不同从 useEffect
到 运行s 与组件挂载(因为 useEffect
的第二个参数是 []
,它 运行s 一次挂载)。
要解决此问题,您通常需要 _searchFilms
设置一个状态变量(类似于 reloadRequested
,但它不一定是布尔值,请参阅下面的文章了解不同的风格) 并有第二个 useEffect
这样的东西:
useEffect(() => {
if (reloadRequested) {
_loadFilms();
setReloadRequested(false);
}
}
, [reloadRequested])
要获得包含大量解释的更完整示例,请阅读这篇文章 https://www.robinwieruch.de/react-hooks-fetch-data。
我正在使用 react-native 实现无限滚动,当我进行搜索时返回结果,如果结果在 API 上有很多页面,当我滚动 API returns 更多数据 .
我的实现在 class 组件上运行良好,但是当我尝试将其转换为工作组件时,当我进行搜索时,会返回数据,如果我进行另一次搜索,则会返回之前的数据仍然显示之前的搜索
class 组件
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
之外 运行 效果(例如 getFilmsWithSearch
)。
来自https://reactjs.org/docs/hooks-reference.html#useeffect
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
当您从 onSubmitEditing={() => _searchFilms()}
事件处理程序中调用 _loadFilms
时,您不在 useEffect
中 运行,这与对 _loadFilms
的调用不同从 useEffect
到 运行s 与组件挂载(因为 useEffect
的第二个参数是 []
,它 运行s 一次挂载)。
要解决此问题,您通常需要 _searchFilms
设置一个状态变量(类似于 reloadRequested
,但它不一定是布尔值,请参阅下面的文章了解不同的风格) 并有第二个 useEffect
这样的东西:
useEffect(() => {
if (reloadRequested) {
_loadFilms();
setReloadRequested(false);
}
}
, [reloadRequested])
要获得包含大量解释的更完整示例,请阅读这篇文章 https://www.robinwieruch.de/react-hooks-fetch-data。