【发布时间】:2020-03-07 11:21:33
【问题描述】:
我正在尝试使用 React Native 将 Class 组件 转换为 Functional。
我的Search 组件允许用户搜索电影名称,我正在调用 API 向他展示所有对应的电影。
这是我的类组件:
class Search 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 })
getFilmsFromApiWithSearchedText(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()
})
}
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) => item.id.toString()}
renderItem={({item}) => <FilmItem film={item}/>}
onEndReachedThreshold={0.5}
onEndReached={() => {
if (this.page < this.totalPages) {
this._loadFilms()
}
}}
/>
</View>
)
}
}
render() {
return (
<View>
<TextInput
onChangeText={(text) => this._searchTextInputChanged(text)}
onSubmitEditing={() => this._searchFilms()}
/>
<Button title='Search' onPress={() => this._searchFilms()}/>
<FlatList
data={this.state.films}
keyExtractor={(item) => item.id.toString()}
renderItem={({item}) => <FilmItem film={item}/>}
onEndReachedThreshold={0.5}
onEndReached={() => {
if (this.page < this.totalPages) {
this._loadFilms()
}
}}
/>
{this._displayLoading()}
</View>
)
}
}
我如何用钩子翻译以下内容:
this.page和this.totalPages? useRef 是解决方案吗?在
_searchFilms()中,当我的电影列表为空时(因为这是一个新搜索),我正在使用setState回调进行新的API 调用。但是之后立即执行是行不通的,因为setState是异步的。 但我找不到用钩子做的方法。
我认为useEffect 可以这样做,但是:
- 我只想在
film列表为空时调用此 API,因为我调用_searchFilms()进行新搜索。 -
_loadFilms()在用户滚动时被调用以向 FlatList 添加更多电影(用于相同的搜索),因此在这种情况下我无法清除this.films。
这是我到目前为止的翻译方式:
const Search = () => {
const [searchText, setSearchText] = useState('');
const [films, setFilms] = useState([]);
// handle pagination
const page = useRef(0);
const totalPages = useRef(0);
// handle api fetch
const [isLoading, setIsLoading] = useState(false);
const loadFilmsFromApi = () => {
getFilmsFromApiWithSearchedText(searchText, page + 1).then((data) => {
page.current = data.page;
totalPages.current = data.total_pages;
setFilms(films => [...films, ...data.results]);
setIsLoading(false);
})
};
const searchFilm = () => {
if (searchText.length > 0) {
page.current = 0;
totalPages.current = 0;
setFilms([]);
// HERE MY Films list won't be cleared (setState asynchronous)
loadFilmsFromApi();
// after the api call, clear input
setSearchText('');
}
};
useEffect(() => {
console.log(page, totalPages, "Film number" + films.length);
}, [films]);
【问题讨论】:
标签: reactjs react-native react-hooks use-effect