componentWillReceivePropsが実行されるときにリストビューを更新しようとしています。これは、取得後にdataSourceが更新されたようです(console.log(this.state.dataSource)をrender()に入れ、エンドポイントの現在のステータスに従って変更します)。componentWillReceivePropsの後にdataSourceが更新されますが、リストビューは反応ネイティブでリフレッシュされません。
ただし、ListViewはそのままです。私はなぜ疑問に思っていたし、dataSourceの疑いがありました。だから私はrender()内のdataSourceを出力するためにstringオブジェクトを作成しました。 var str = JSON.stringify(this.state.dataSource._dataBlob.s1);
そして<View><Text>{str}</Text>
上記一部変更componentWillReceiveProps()が実行されたとき。ただし、リストビューは同じままです。私はこれがなぜ起こるのかを知りません。
ここに私のコードのスニペットがあります。
componentWillReceiveProps(){
var query = ApiUrl.urlForWeekInfo(this.state.email);
console.log(query);
this._executeQuery(query,3);
}
constructor(props) {
super(props);
var dataSource = new ListView.DataSource(
{rowHasChanged: (r1, r2) => r1.guid !== r2.guid});
this.state = {
isLoading: false,
...
first_name: this.props.first_name,
email: this.props.email,
dataSource: dataSource.cloneWithRows(this.props.listings)
};
}
..
_executeQuery(query,i) {
this.setState({ isLoading: true });
fetch(query)
.then(response => response.json())
.then(json => this._handleResponse(json.response,i))
.catch(error =>
this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));
}
_handleResponse(response,i) {
this.setState({ isLoading: false , message: '' });
if (response.application_response_code.substr(0, 1) === '1') {
if(i==1){
this.props.navigator.push({
title: 'Apply',
component: Apply,
passProps: {listings: response.listings, times: response.timetable, week_num: this.state.week_num}
});
} else if (i==3){
var output = response.listings;
this.setState({
dataSource: this.state.dataSource.cloneWithRows(output)
});
console.log(response.listings);
this.forceUpdate();
}
} else {
}
}
render() {
console.log(this.state.dataSource._dataBlob.s1);
var str = JSON.stringify(this.state.dataSource._dataBlob.s1);
var listviewsource = this.state.dataSource;
return (
<View style={[this.border('red'), styles.container_top]}>
<View style={[this.border('black'), styles.container_top_buttons]} >
<ListView
dataSource={listviewsource}
renderRow={this.renderRow.bind(this)}/>
</View>
{spinner}
<View>
<Text>{str}</Text>
</View>
</View>
);
}}
ご意見やご経験があれば教えてください。
私はこの問題の解決策を見つけることになった:
var array = response.listings;
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
//=> call another ds variable.
this.setState({
rawData: array,
dataSource: ds.cloneWithRows(response.listings)
});
私の場合は、連結したり前に付ける必要はありませんが、すべてをすべてリロードします。 cloneWithRows文でdataSourceに触れたとしても、それは私のためには機能しませんでした。私は '新しいListView'を使用しようとした、それは動作するようになります!あなたはそのようなやり方をすることに否定的な側面を示唆しますか? –
@SungpahLee何も本当に!あなたがしたことは、私のスニペットと本質的に同じです。私は 'getInitialState()'に '新しいListView'を持っていて、あなたは' constructor() 'で同じものを持っています。だからIMO私はこのアプローチの欠点は見当たりません。しかし、他の見解を歓迎します。また、連結の代わりにデータを直接置き換えることもできます。これらの基本的な操作よりも、Gistは重要です。データを再レンダリングする場合は、 'cloneWithRows(newdata)'を呼び出してstate.dataSourceを更新するだけで済みます。 – Mihir