以下に示すように、Redux を使用してRecyclerListView
( Flipkart Github ) を実装しました。が呼び出されて新しいデータのバッチが送信された場合を除いて、すべてがうまく機能しているように見えますonEndReached
。リストは滑らかなままではなく、ページの上部に配置されます。以下の GIF でその動作を確認してください。
注: これは web (chrome) で発生しています。最新の安定版と 2.0.13-alpha.1 を試してみました
import React, { useCallback } from 'react';
import { View, Text, Dimensions } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import { RecyclerListView, DataProvider, LayoutProvider } from 'recyclerlistview/web';
import { createSelector } from 'reselect';
import { loadData } from '../actions';
const selectData = createSelector(
state => state.data,
data => Object.values(data),
);
let containerCount = 0;
class CellContainer extends React.Component {
constructor(args) {
super(args);
this._containerId = containerCount++;
}
render() {
return (
<View {...this.props}>
{this.props.children}
<Text>Cell Id: {this._containerId}</Text>
</View>
);
}
}
const List = ({ isServer }) => {
let { width } = Dimensions.get('window');
const dispatch = useDispatch();
const data = useSelector(selectData);
const dataDataProvider = new DataProvider((r1, r2) => {
return r1 !== r2;
}).cloneWithRows(data);
const onEndReached = useCallback(() => dispatch(loadData()), [dispatch]);
const layoutProvider = new LayoutProvider(
() => 0,
(type, dim) => {
dim.width = width;
dim.height = 240;
},
);
const rowRenderer = (type, data) => {
return <CellContainer />;
};
return (
<View
style={{
display: "flex",
flex: 1,
width: "100vw",
height: "100vh"
}}
>
<RecyclerListView
layoutProvider={layoutProvider}
dataProvider={dataDataProvider}
onEndReached={onEndReached}
rowRenderer={rowRenderer}
/>
</View>
);
};
export default List;
更新: redux connect を使用して、クラスベースのバージョンが問題なく動作することを確認できます。これに傾いているのは、ライブラリとのある種の非互換性です。それにもかかわらず興味深い。
以下のスニペットは、このデモの単純化された実例ですhttps://codesandbox.io/s/k54j2zx977
class App extends React.Component {
constructor(props) {
let { width } = Dimensions.get('window');
super(props);
this.state = {
dataProvider: new DataProvider((r1, r2) => {
return r1 !== r2;
}),
layoutProvider: new LayoutProvider(
index => 0,
(type, dim) => {
dim.width = width;
dim.height = 240;
},
),
count: 0,
};
}
componentDidUpdate(prevProps) {
if (this.props.data.length !== prevProps.data.length) {
this.setState({
dataProvider: this.state.dataProvider.cloneWithRows(this.props.data),
count: this.props.data.length
});
}
}
componentWillMount() {
this.props.loadData();
}
async fetchMoreData() {
this.props.loadData();
}
rowRenderer = (type, data) => {
//We have only one view type so not checks are needed here
return <CellContainer />;
};
handleListEnd = () => {
this.fetchMoreData();
//This is necessary to ensure that activity indicator inside footer gets rendered. This is required given the implementation I have done in this sample
this.setState({});
};
render() {
//Only render RLV once you have the data
return (
<View style={styles.container}>
{this.state.count > 0 ? (
<RecyclerListView
style={{ flex: 1 }}
contentContainerStyle={{ margin: 3 }}
onEndReached={this.handleListEnd}
dataProvider={this.state.dataProvider}
layoutProvider={this.state.layoutProvider}
renderAheadOffset={0}
rowRenderer={this.rowRenderer}
/>
) : null}
</View>
);
}
}
export default connect(
state => ({
data: selectData(state),
}),
dispatch => bindActionCreators({ loadData }, dispatch),
)(App);