使用axios发起POST请求后如何拉取新数据并重新渲染FlatList?
问题根因
现有代码中列表拉取逻辑仅在ListScreen的componentDidMount钩子中执行,该钩子只会在组件首次挂载时触发一次。POST请求逻辑在独立的Create组件中维护,两个组件状态完全隔离:
- 即使在POST成功回调中重新发起GET请求,拿到的新数据也仅在Create组件作用域内,无法直接修改ListScreen的
data状态 - 若Create和ListScreen为独立路由页面,提交完成后若未触发ListScreen重新挂载,组件不会自动重新拉取数据
可行解决方案
方案1:路由回调触发列表刷新(改造成本最低,适合页面跳转场景)
如果使用React Navigation/React Router等路由方案实现页面跳转,从列表页跳转到创建页时,把刷新列表的方法作为参数传给创建页,POST成功后调用该方法再返回列表页即可。
首先修改ListScreen代码,把拉取数据的逻辑抽为独立可复用的方法:
class ListScreen extends Component { constructor(props) { super(props); this.state = { data: [], } } // 抽离拉取列表逻辑,方便后续重复调用 fetchListData = () => { axios.get('insert url') .then(res => { this.setState({ data: res && res.data ? res.data : [] }) }) .catch(err => { console.log('Run into problem') }) } componentDidMount() { // 首次挂载时调用拉取方法 this.fetchListData() } goToCreatePage = () => { // 跳转到创建页时,把刷新方法作为路由参数传递,以下以React Navigation写法为例 this.props.navigation.navigate('Create', { refreshList: this.fetchListData }) } render() { const { data } = this.state; return ( <View> <Button title="新建联系人" onPress={this.goToCreatePage} /> <FlatList data={data} renderItem={({ item }) => { return ( <Item name={item.lastName} phone={item.phoneNumber} /> ); }} keyExtractor={(item) => item.id} /> </View> ) } }
再修改Create组件的提交逻辑,POST成功后调用传入的刷新方法:
class Create extends Component { handleSubmitData = (value) => { console.log('check value: ', value) axios.post('insert url', { lastName: `${value.Name}`, phoneNumber: `${value.Phone}`, }) .then((response) => { console.log('here is what you upload: ', response.data) // 取出路由参数里的刷新方法 const { refreshList } = this.props.route.params; // 调用方法重新拉取全量列表 refreshList(); // 返回列表页 this.props.navigation.goBack(); }) .catch((err) => { console.log('Run into problem') }) } render() { return ( <CreateForm handleSubmitData={this.handleSubmitData} /> ) } }
方案2:本地直接更新列表状态(性能更优,无需重复请求全量数据)
mockapi.io的POST请求成功后,响应体会直接返回带唯一id的新创建条目,可直接将该条目拼接到原有列表的state中,省去一次GET请求的网络开销。
修改Create组件的POST成功回调,直接把新条目传回列表页:
.then((response) => { console.log('here is what you upload: ', response.data) const { addNewItem } = this.props.route.params; // 把接口返回的新条目传给列表页的更新方法 addNewItem(response.data); this.props.navigation.goBack(); })
在ListScreen中新增追加条目的方法,跳转创建页时传入:
// 把新条目追加到列表头部 addNewItemToList = (newItem) => { this.setState(prevState => ({ data: [newItem, ...prevState.data] })) } goToCreatePage = () => { this.props.navigation.navigate('Create', { addNewItem: this.addNewItemToList }) }
注意事项
- 检查
CreateForm的提交绑定逻辑:当前代码中从props解构了handleSubmit,但传入按钮onPress的是this.props.handleSubmitData,如果使用redux-form等表单库,需确认绑定逻辑正确,避免提交事件未正常触发 - 若两个组件为父子嵌套关系而非独立路由页面,直接将列表更新方法通过props从ListScreen传递给Create组件即可,无需通过路由参数传值
- 若项目接入了全局状态管理(Redux/Mobx/Context),可将列表数据存入全局store,POST成功后直接更新全局store中的列表数据,所有引用该数据的组件会自动触发重渲染
内容的提问来源于stack exchange,提问作者Xwind
相关产品推荐
相关产品推荐

