Javascript 使用getDerivedStateFromProps获取API数据会导致组件多次渲染
我正在尝试从API调用中获取一些数据。我正在使用Javascript 使用getDerivedStateFromProps获取API数据会导致组件多次渲染,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我正在尝试从API调用中获取一些数据。我正在使用getDerivedStateFromProps,componentDidMount,shouldcomonentupdate和componentdiddupdate` 我这样做是因为我需要userToken,它来自userToken:store.signnscreen.userToken,在调用函数getPassengerData之前到达那里,该函数需要userToken从API获取数据 这是整个组件: // imports class Hom
getDerivedStateFromProps
,componentDidMount,
shouldcomonentupdate和
componentdiddupdate`
我这样做是因为我需要userToken
,它来自userToken:store.signnscreen.userToken
,在调用函数getPassengerData
之前到达那里,该函数需要userToken
从API获取数据
这是整个组件:
// imports
class HomeScreen extends Component {
static navigationOptions = {
header: null,
};
state = {
error: false,
};
static getDerivedStateFromProps(props, state) {
if (props.userToken !== state.userToken) {
return { userToken: props.userToken };
}
return null;
}
componentDidMount() {
this.GetPassengersData();
}
shouldComponentUpdate(prevProps, state) {
return this.props !== prevProps;
}
componentDidUpdate(prevProps, prevState) {
const { error } = this.state;
if (!error) {
this.GetPassengersData();
}
}
GetPassengersData = async () => {
const { passengersDataActionHandler, userToken } = this.props;
if (userToken && userToken !== null) {
try {
const response = await fetch(
'http://myAPI/public/api/getPassengers',
{
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
const responseJson = await response.json();
if (has(responseJson, 'error')) {
this.setState({ error: true });
Alert.alert('Error', 'Please check your credentials.');
} else {
passengersDataActionHandler(responseJson.success.data);
}
} catch (error) {
this.setState({ error: true });
Alert.alert(
'Error',
'There was an error with your request, please try again later.',
);
}
}
};
render() {
return <TabView style={styles.container} />;
}
}
HomeScreen.defaultProps = {
userToken: null,
};
HomeScreen.propTypes = {
navigation: PropTypes.shape({}).isRequired,
passengersDataActionHandler: PropTypes.func.isRequired,
userToken: PropTypes.oneOfType([PropTypes.string]),
};
export default compose(
connect(
store => ({
userToken: store.signinScreen.userToken,
passengersData: store.homeScreen.passengersData,
}),
dispatch => ({
passengersDataActionHandler: token => {
dispatch(passengersDataAction(token));
},
}),
),
)(HomeScreen);
//导入
类主屏幕扩展组件{
静态导航选项={
标题:null,
};
状态={
错误:false,
};
静态getDerivedStateFromProps(props,状态){
if(props.userToken!==state.userToken){
返回{userToken:props.userToken};
}
返回null;
}
componentDidMount(){
这是.GetPassengersData();
}
shouldComponentUpdate(prevProps,状态){
返回this.props!==prevProps;
}
componentDidUpdate(prevProps、prevState){
const{error}=this.state;
如果(!错误){
这是.GetPassengersData();
}
}
GetPassengersData=async()=>{
const{passengersDataActionHandler,userToken}=this.props;
if(userToken&&userToken!==null){
试一试{
const response=等待获取(
'http://myAPI/public/api/getPassengers',
{
方法:“POST”,
标题:{
授权:`Bearer${userToken}`,
接受:'application/json',
“内容类型”:“应用程序/json”,
},
},
);
const responseJson=wait response.json();
if(has(responseJson,'error')){
this.setState({error:true});
Alert.Alert('错误','请检查您的凭据');
}否则{
passengersDataActionHandler(responseJson.success.data);
}
}捕获(错误){
this.setState({error:true});
警惕,警惕(
“错误”,
“您的请求出错,请稍后再试。”,
);
}
}
};
render(){
返回;
}
}
HomeScreen.defaultProps={
userToken:null,
};
主屏幕.propTypes={
导航:PropTypes.shape({}).isRequired,
passengersDataActionHandler:PropTypes.func.isRequired,
userToken:PropTypes.oneOfType([PropTypes.string]),
};
导出默认组合(
连接(
商店=>({
userToken:store.signnscreen.userToken,
乘客数据:store.homeScreen.passengersData,
}),
分派=>({
passengersDataActionHandler:token=>{
调度(passengersDataAction(令牌));
},
}),
),
)(主屏幕);
使用此实现,组件会多次渲染,因此会中断应用程序
我可能做错了什么?首先,您不需要在状态中存储
userToken
,因为您没有在本地修改它,因此不需要getDerivedStateFromProps
其次,您需要仅在属性更改时触发componentDidUpdate中的API调用,而不是在没有检查的情况下直接触发,否则,API成功或错误中的setState将导致组件再次重新呈现调用componentDidUpdate
,从而再次调用API,从而导致无限循环
第三,shouldComponentUpdate比较道具内部的检查并不完全正确,因为nestedObjects道具将给出假阴性结果,而且如果为道具编写深度相等性检查,如果状态更改,组件将不会重新渲染
// imports
class HomeScreen extends Component {
static navigationOptions = {
header: null,
};
state = {
error: false,
};
componentDidMount() {
this.GetPassengersData();
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.userToken !== this.props.userToken) {
this.GetPassengersData();
}
}
GetPassengersData = async () => {
const { passengersDataActionHandler, userToken } = this.props;
if (userToken && userToken !== null) {
try {
const response = await fetch(
'http://myAPI/public/api/getPassengers',
{
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
const responseJson = await response.json();
if (has(responseJson, 'error')) {
this.setState({ error: true });
Alert.alert('Error', 'Please check your credentials.');
} else {
passengersDataActionHandler(responseJson.success.data);
}
} catch (error) {
this.setState({ error: true });
Alert.alert(
'Error',
'There was an error with your request, please try again later.',
);
}
}
};
render() {
return <TabView style={styles.container} />;
}
}
HomeScreen.defaultProps = {
userToken: null,
};
HomeScreen.propTypes = {
navigation: PropTypes.shape({}).isRequired,
passengersDataActionHandler: PropTypes.func.isRequired,
userToken: PropTypes.oneOfType([PropTypes.string]),
};
export default compose(
connect(
store => ({
userToken: store.signinScreen.userToken,
passengersData: store.homeScreen.passengersData,
}),
dispatch => ({
passengersDataActionHandler: token => {
dispatch(passengersDataAction(token));
},
}),
),
)(HomeScreen);
//导入
类主屏幕扩展组件{
静态导航选项={
标题:null,
};
状态={
错误:false,
};
componentDidMount(){
这是.GetPassengersData();
}
componentDidUpdate(prevProps、prevState){
if(prevProps.userToken!==此.props.userToken){
这是.GetPassengersData();
}
}
GetPassengersData=async()=>{
const{passengersDataActionHandler,userToken}=this.props;
if(userToken&&userToken!==null){
试一试{
const response=等待获取(
'http://myAPI/public/api/getPassengers',
{
方法:“POST”,
标题:{
授权:`Bearer${userToken}`,
接受:'application/json',
“内容类型”:“应用程序/json”,
},
},
);
const responseJson=wait response.json();
if(has(responseJson,'error')){
this.setState({error:true});
Alert.Alert('错误','请检查您的凭据');
}否则{
passengersDataActionHandler(responseJson.success.data);
}
}捕获(错误){
this.setState({error:true});
警惕,警惕(
“错误”,
“您的请求出错,请稍后再试。”,
);
}
}
};
render(){
返回;
}
}
HomeScreen.defaultProps={
userToken:null,
};
主屏幕.propTypes={
导航:PropTypes.shape({}).isRequired,
passengersDataActionHandler:PropTypes.func.isRequired,
userToken:PropTypes.oneOfType([PropTypes.string]),
};
导出默认组合(
连接(
商店=>({
userToken:store.signnscreen.userToken,
乘客数据:store.homeScreen.passengersData,
}),
分派=>({
passengersDataActionHandler:token=>{
调度(passengersDataAction(令牌));
},
}),
),
)(主屏幕);
您可以在getPassengerData()
中设置状态。如果状态
已更新,则将执行组件更新()。这是inf循环。