首页 > 解决方案 > 在我的情况下,如何解决“超出最大更新深度”?

问题描述

我正在使用 React 在 Ionic 中开发应用程序,但出现此错误:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

我创建了一个表单来更新一些在后端调用 api 请求的数据。

Request: put /xx/xx/update
Body Request: 
{
    "titleId": "1",
    "firstName": "Ani",  
}
Response:
{
    "title": {
        "1": "Dr"
    },
    "firstName": "Ani",
}

在功能组件 MyData.tsx 内部:

const MyData: React.FC = () => {

//title and firstName come from React Context, I'm using them in the whole app

 const {
    firstName,
    setFirstName,
    title,
    setTitle,
    iserror,
    setIserror,
  } = React.useContext(AuthContext);

  const history = useHistory();
  const authHeader = AuthHeader.getAuthHeader();

const updateData = () => {
    const data = {
      titleId: title,
      firstName: firstName,
    };

axios
      .put("/xx/xx/update", data, { headers: authHeader })
      .then((response) => {

        setTitle(response.data.title);
        setFirstName(response.data.firstName);
     
        return response.data;
      })
      .catch((error) => {
        setMessage(
          "Please check your data and try again"
        );
        setIserror(true);
      });
  };

return (
    <React.Fragment>
      <IonPage className="ion-page" id="main-content">
        
        <IonContent className="ion-padding">
          <h1>Change your data</h1>
          <form className="ion-padding">
            <IonItem>
              <IonLabel position="floating">Title</IonLabel>
              <IonSelect
                value={Object.keys(title)} // this row causes the problem
                onIonChange={(e) => setTitle(e.detail.value!)}
              >
                <IonSelectOption value="0"></IonSelectOption>
                <IonSelectOption value="1">Dr</IonSelectOption>
                <IonSelectOption value="2">Dr.-Ing</IonSelectOption>
                <IonSelectOption value="3">Professor</IonSelectOption>
                <IonSelectOption value="4">Prof.-Dr</IonSelectOption>
              </IonSelect>
            </IonItem>
           
            <IonItem>
              <IonLabel position="floating">Name*</IonLabel>
              <IonInput
                required
                value={firstName}
                onIonChange={(e) => setFirstName(e.detail.value!)}
              ></IonInput>
            </IonItem>
            
            <IonButton
              className="ion-margin-top"
              expand="block"
              onClick={(e) => {
                e.preventDefault();
                updateData();
                history.goBack();
              }}
            >
              Save changes
            </IonButton>
          </form>
        </IonContent>
      </IonPage>
    </React.Fragment>
  );
};
export default MyData;

value={Object.keys(title)} ==> 我需要在打开表单时显示所选字段 'Title' 的实际值,这就是我需要 'value' 属性的原因,但这会导致错误。如果我删除这行代码,我可以成功更新标题和名称。当我再次打开表单时,没有显示标题的实际值,只有“名称”。

我是 React/Ionic/Typescript 的新手,任何帮助都将不胜感激。

谢谢!阿尼

标签: javascriptreactjstypescriptionic-framework

解决方案


您需要将您的请求移动axiosuseEffect反应钩子中:

React.useEffect(() => {
  axios
      .put("/xx/xx/update", data, { headers: authHeader })
      .then((response) => {

        setTitle(response.data.title);
        setFirstName(response.data.firstName);
     
        return response.data;
      })
      .catch((error) => {
        setMessage(
          "Please check your data and try again"
        );
        setIserror(true);
      });
  };
}, [])

问题是您的 axios 请求会导致重新渲染,而重新渲染会导致 axios 请求,而 axios 请求会导致重新渲染...

因此,如果您将您的 axios 请求包装在 useEffect 中,您的请求将只发出一次。


推荐阅读