如何让 componentDidMount 再次渲染?
Posted
技术标签:
【中文标题】如何让 componentDidMount 再次渲染?【英文标题】:How can I make componentDidMount render again? 【发布时间】:2020-04-15 13:14:11 【问题描述】:我在探索组件中获取 api(makeup API) 并在探索按钮中使用它。 我将品牌作为 ExploreButtons 中的一个按钮。当我单击 ExploreButtons 的 FlatList 元素中的按钮时,我想在 ExploreButtons 的第二个 FlatList 中查看来自 api 的图像。当我单击按钮时,componentDidMount 是否可以重新呈现?
import React, Component from 'react'
import View from 'react-native'
import ExploreButtons from './ExploreButtons'
export default class Explore extends Component
constructor(props)
super(props);
this.state =
isLoading: true,
makeupApi: 'http://makeup-api.herokuapp.com/api/v1/products.json',
callbackFunction = (item) =>
this.setState(
makeupApi: 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=' + item,
)
async componentDidMount()
try
const response = await fetch(this.state.makeupApi);
const responseJson = await response.json();
this.setState(
isLoading: false,
dataSource: responseJson,
, function ()
);
const reformattedArray = this.state.dataSource.map(obj =>
var rObj = ;
rObj = obj.brand;
return rObj;
);
this.setState(
duplicatesRemoved: reformattedArray.filter((item, index) => reformattedArray.indexOf(item) === index)
)
catch (error)
console.error(error);
;
render()
console.log(this.state.makeupApi)
return (
<View style= flex: 1 >
<ExploreButtons
api=this.state.dataSource
removedDuplicatesFromAPI=this.state.duplicatesRemoved
parentCallback=this.callbackFunction
makeupApi= this.state.makeupApi />
</View>
)
export default class ExploreButtons extends Component
getBrandImages = (item) =>
this.props.parentCallback(item)
render()
return (
<View style= flex: 1 >
<View>
<FlatList
horizontal
showsHorizontalScrollIndicator=false
data=this.props.removedDuplicatesFromAPI
renderItem=( item ) =>
<TouchableOpacity
style=styles.exploreButtons
onPress=() =>
this.getBrandImages(item)
>
<Text>item</Text>
</TouchableOpacity>
keyExtractor=item => item
/>
</View>
<View>
<FlatList
data=this.props.api
renderItem=( item ) =>
<View>
<Image source= uri: item.image_link
style=
alignSelf: "center",
width: '100%',
height: 300,
/>
</View>
keyExtractor=item => item.id.toString() />
</View>
</View>
)
【问题讨论】:
【参考方案1】:您可以将componentDidMount
中的所有逻辑放在另一个函数上,并在您调用回调时调用它。作为第一个非常粗略的方法,这将起作用:
注意:你并不真的需要状态中的API URL,将item放在状态上并基于它构造URL。
import React, Component from 'react';
import View from 'react-native';
import ExploreButtons from './ExploreButtons';
export default class Explore extends Component
API_URL = 'http://makeup-api.herokuapp.com/api/v1/products.json';
constructor(props)
super(props);
this.state =
isLoading: true,
item: null,
dataSource: null,
duplicatesRemoved: [],
;
getAPIURL(item)
if(!item)
return API_URL
return `$API_URL?brand=$item`;
async fetchData(item)
try
const url = getAPIURL(item);
const response = await fetch(url);
const responseJson = await response.json();
this.setState(
isLoading: false,
dataSource: responseJson,
item,
);
const reformattedArray = responseJSON.map(( brand ) => brand);
this.setState(
duplicatesRemoved: reformattedArray.filter(
(item, index) => reformattedArray.indexOf(item) === index,
),
);
catch (error)
console.error(error);
async componentDidMount()
fetchData();
render()
const dataSource, duplicatesRemoved, item = this.state;
return (
<View style= flex: 1 >
<ExploreButtons
api=dataSource
removedDuplicatesFromAPI=duplicatesRemoved
parentCallback=this.fetchData
makeupApi=getURL(item)
/>
</View>
);
export default class ExploreButtons extends Component
getBrandImages = item =>
this.props.parentCallback(item);
;
render()
const removedDuplicatesFromAPI, api = this.props;
return (
<View style= flex: 1 >
<View>
<FlatList
horizontal
showsHorizontalScrollIndicator=false
data=removedDuplicatesFromAPI
renderItem=( item ) => (
<TouchableOpacity
style=styles.exploreButtons
onPress=() =>
this.getBrandImages(item);
>
<Text>item</Text>
</TouchableOpacity>
)
keyExtractor=item => item
/>
</View>
<View>
<FlatList
data=api
renderItem=( item ) => (
<View>
<Image
source= uri: item.image_link
style=
alignSelf: 'center',
width: '100%',
height: 300,
/>
</View>
)
keyExtractor=item => item.id.toString()
/>
</View>
</View>
);
【讨论】:
它说可能未处理的 Promise Rejection (id: 0): ReferenceError: fetchData is not defined ReferenceError: fetchData is not defined 您需要在fetchData
之前添加await
和/或将其包装在try catch
块上
有item时返回Network request failed---- let url = !item ? this.API_URL : console.log(item);/* this.API_URL + '?brand=' + item */;
好吧,当有item时打印URL是什么,然后尝试调用API看看它返回什么。【参考方案2】:
如何让 componentDidMount 再次渲染?
不确定您的意思,但我认为您要问的是How can I make componentDidMount *run* again?
,要做到这一点,您需要在callbackFunction
中使用相同的代码才能再次运行它。 componentDidMount
只会在组件第一次渲染后运行。
还要注意,如果你想重新渲染FlatList
,你需要传递extraData
,这样它就知道它需要重新渲染。
【讨论】:
以上是关于如何让 componentDidMount 再次渲染?的主要内容,如果未能解决你的问题,请参考以下文章
ReactJs:如何在渲染之前等待 componentDidMount() 完成?
如何更新 componentDidMount 中的上下文状态?
React Native this.setState() 仅在再次与组件交互后重新渲染
React Child componentDidMount不在Route上触发