Я реализую очень простой список, который вызывает сервер, который возвращает страницу, содержащую книги. Каждая книга имеет название, автора, идентификатор, numberOfPages и цену).Я использую плоский список для бесконечной прокрутки, и он хорошо выполняет свою работу два раза подряд (загружает первые три страницы), но позже он больше не вызывает обработчик.
Первоначально онработал очень хорошо, выбирая все доступные страницы, но он перестал работать правильно после того, как я добавил эту дополнительную проверку в локальное хранилище.Если страница доступна в локальном хранилище и просуществовала не более 5 секунд, я не получаю данные с сервера, а использую страницу, которая кэшируется.Конечно, если доступной страницы нет или она слишком старая, я извлекаю ее с сервера и после сохранения в локальном хранилище (что-то пошло не так после добавления этого поведения, связанного с локальным хранилищем).
Здесьэто мой компонент:
export class BooksList extends Component {
constructor(props) {
super(props);
this.state = {
pageNumber: 0
};
}
async storePage(page, currentTime) {
try {
page.currentTime = currentTime;
await AsyncStorage.setItem(`page${page.page}`, JSON.stringify(page));
} catch (error) {
console.log(error);
}
}
subscribeToStore = () => {
const { store } = this.props;
this.unsubsribe = store.subscribe(() => {
try {
const { isLoading, page, issue } = store.getState().books;
if (!issue && !isLoading && page) {
this.setState({
isLoading,
books: (this.state.books ?
this.state.books.concat(page.content) :
page.content),
issue
}, () => this.storePage(page, new Date()));
}
} catch (error) {
console.log(error);
}
});
}
componentDidMount() {
this.subscribeToStore();
// this.getBooks();
this.loadNextPage();
}
componentWillUnmount() {
this.unsubsribe();
}
loadNextPage = () => {
this.setState({ pageNumber: this.state.pageNumber + 1 },
async () => {
let localPage = await AsyncStorage.getItem(`page${this.state.pageNumber}`);
let pageParsed = JSON.parse(localPage);
if (localPage && (new Date().getTime() - localPage.currentTime) < 5000) {
this.setState({
books: (
this.state.books ?
this.state.books.concat(pageParsed.content) :
page.content),
isLoading: false,
issue: null
});
} else {
const { token, store } = this.props;
store.dispatch(fetchBooks(token, this.state.pageNumber));
}
});
}
render() {
const { isLoading, issue, books } = this.state;
return (
<View style={{ flex: 1 }}>
<ActivityIndicator animating={isLoading} size='large' />
{issue && <Text>issue</Text>}
{books && <FlatList
data={books}
keyExtractor={book => book.id.toString()}
renderItem={this.renderItem}
renderItem={({ item }) => (
<BookView key={item.id} title={item.title} author={item.author}
pagesNumber={item.pagesNumber} />
)}
onEndReachedThreshold={0}
onEndReached={this.loadNextPage}
/>}
</View>
)
}
}
В начале номер страницы, доступный в состоянии компонента, равен 0, поэтому при первой загрузке первой страницы с сервера он будет увеличиваться перед остальным вызовом.
А вот и действие fetchBooks (токен, номер страницы):
export const fetchBooks = (token, pageNumber) => dispatch => {
dispatch({ type: LOAD_STARTED });
fetch(`${httpApiUrl}/books?pageNumber=${pageNumber}`, {
headers: {
'Authorization': token
}
})
.then(page => page.json())
.then(pageJson => dispatch({ type: LOAD_SUCCEDED, payload: pageJson }))
.catch(issue => dispatch({ type: LOAD_FAILED, issue }));
}
Спасибо!