reactjs - Ionic/React/TypeScript,react-router 导航动画触发两次

标签 reactjs ionic-framework react-router

所以基本上我正在开发一个 Ionic/React Typescript 应用程序,当我浏览应用程序时,这个奇怪的页面转换发生了两次(见下面的 gif)

我检查过,它不是两次调用的渲染,因为 componentWillMount/didMount/willUnmount 都触发了一次,就像推送页面和推送页面一样。

enter image description here

如您所见,转换总是发生两次并且在任何地方都找不到解决方案......使用的版本: - Ionic :5.2.1 - React :16.9.0(npm 包) - Typescript 3.6.3(npm 包)

Here is the code for the page with the "Diplomes" Title:

class Diplome extends React.Component<RouteComponentProps> {

  // Function who redirect to the url for edit an situation
  redirectUrlToEditSituation = () => {
    this.props.history.push('/app/edit/diplome/', null);
  }

  render() {
    return (
      <IonPage>
          <IonHeader>
            <IonToolbar>
                <ButtonHambToolBar />
                <ToolBarLogo toolbarName={ToolBarName.DIPLOME}/>
            </IonToolbar>
          </IonHeader>
          <IonContent>
            <FabButtonAction ClickHandler={() => this.redirectUrlToEditSituation()} icon={add}/>
            <GenericList type={ModelType.DIPLOME}/>
          </IonContent>
      </IonPage>
    );
  }
}

export default (Diplome);

这是单击按钮时带有“版本”标题的页面:
class DiplomeEdit extends Component<DiplomeEditProps, {
    dataIsLoad: boolean,
    label_field: string,
    isAnCreate: boolean,
    openModalDelete: boolean,
    isValidation: boolean,
    currentDiplome: any
}>
{

    constructor(props: DiplomeEditProps) {
        super(props);
        this.state = {
            label_field: '',
            isAnCreate: true,
            openModalDelete: false,
            dataIsLoad: false,
            currentDiplome: '',
            isValidation: false,
        };
    }

    async componentWillMount() {
        console.log("component will mount");
        await this.getCurrentDiplomeToUpdate();
    }

    // Function who check if they are param on the url
    // If param exist get the current diplome on the store
    getCurrentDiplomeToUpdate = async () => {
        if (this.props.match.params.idDiplome !== undefined) {

            const diplomes: DiplomeInterface[] = this.props.diplomes;
            if (diplomes.length > 0) {
                const currentDiplomeReceive: DiplomeInterface | undefined = diplomes.find((res: DiplomeInterface) => {
                    return this.props.match.params.idDiplome === res.idDiplome;
                });

                if (currentDiplomeReceive !== undefined) {
                    this.setState({
                        isAnCreate: false,
                        label_field: currentDiplomeReceive.labelDiplome,
                        currentDiplome: currentDiplomeReceive,
                        dataIsLoad: true,
                    });
                }
            }

        } else {
            this.setState({
                isAnCreate: true,
                dataIsLoad: true,
            });
        }
    }

    // Function who render update button
    renderUpdateButton = () => {
        return (
            <div className="contenaire_button_action_situation_edit">
                <Button hidden={this.state.isAnCreate}
                    onClick={() => this.openOrCloseModalDeleteDialog()}
                    className="button_delete_situation">Supprimer</Button>
                <Button
                    onClick={e => this.actionClick()}
                    className="button_action_situation_edit">Enregistrer</Button>
            </div>
        );
    }

    // Function who delete diplome on the databse and on the store
    removeDiplome = async () => {
        await REQUEST.deleteDiplome(this.state.currentDiplome.idDiplome);
        store.dispatch(DELETE_DIPLOME(this.state.currentDiplome.idDiplome));
        this.props.history.replace('/app/diplomes');
    }

    // Function who get the label and id for create new diplome on the databae
    // Reset the state to the default init
    saveDiplome = async () => {
        const obj: DiplomeInterface = {
            idDiplome: Math.random().toString(36).substr(2, 9),
            labelDiplome: this.state.label_field.toLowerCase(),
        };
        this.setState({
            label_field: '',
            isAnCreate: false,
            openModalDelete: false,
        });
        await REQUEST.postDiplome(obj);
        store.dispatch(ADD_DIPLOME(obj));
        //this.props.history.replace('/app/diplomes');
        window.smartAlert("Diplome ajouté avec succès", "success", 5000);
        this.props.history.goBack();
    }

    // Function who update a diplome on the store
    // Need the current diplome
    // Label update
    updateDiplome = async () => {
        const currentDiplomeReceive: DiplomeInterface = this.state.currentDiplome;

        const obj: DiplomeInterface = {
            idDiplome: currentDiplomeReceive.idDiplome,
            labelDiplome: this.state.label_field,
        };

        if (this.props.userConnected.typeAccount === TypeConnect.ADMIN) {
            await REQUEST.updateDiplome(obj);
            store.dispatch(UPDATE_DIPLOME(obj));
            this.props.history.replace('/app/diplomes');
        }
    }

    // Function who checked what action we need
    actionClick = () => {
        if (this.state.isAnCreate) {
            this.saveDiplome();
        } else {
            this.updateDiplome();
        }
    }

    // Function call when input change
    inputChange = (e: any) => {
        this.setState({
            label_field: e.target.value,
        });
    }

    // Function who change the openModalDelete to true
    openOrCloseModalDeleteDialog = () => {
        if (this.props.userConnected.typeAccount === TypeConnect.ADMIN) {
            this.setState({
                openModalDelete: !this.state.openModalDelete,
            });
        }
    }

    render() {

        return (
            <IonPage>
                <IonHeader>
                    <IonToolbar className="task_cat_toolbar">
                        <IonBackButton
                            className="situation_edit_back_button" />
                        <ToolBarLogo toolbarName={ToolBarName.EDIT} />
                    </IonToolbar>
                </IonHeader>

                <IonContent>
                    <div className="contenaire_edit">
                        <div className="contenaire_form_situation">
                            <div className="contenaire_field">
                                <TextField
                                    onChange={e => this.inputChange(e)}
                                    value={this.state.label_field}
                                    className="field_form_situation"
                                    label="Libelle" />
                            </div>

                            <div className="container_task_situation_edit">

                                {!this.state.dataIsLoad && <SpinnerCircular />}

                                {this.renderUpdateButton()}

                                {
                                    this.state.openModalDelete &&
                                    <DialogDelete
                                        actionRemove={() => this.removeDiplome()}
                                        open={this.state.openModalDelete}
                                        actionCloseModal={() => this.openOrCloseModalDeleteDialog()} />
                                }

                            </div>
                        </div>
                    </div>
                </IonContent>

            </IonPage>
        );
    }

}

const mapStateToProps = (state: DiplomeEditProps) => ({
    diplomes: state.diplomes,
    network: state.network,
    role: state.role,
    userConnected: state.userConnected,
});

export default connect(mapStateToProps)(DiplomeEdit);

最佳答案

我面临同样的问题。似乎 Ionic React 与历史和位置 Prop 不匹配。 check out this GitHub issue .
我设法通过用 React.memo 包装我的组件来解决我的问题,而不是使用历史来推送,我使用了来自 react-router-dom 的 Redirect 和一个要重定向的状态。

关于reactjs - Ionic/React/TypeScript,react-router 导航动画触发两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62405424/

相关文章:

javascript - React Router 的 Props 错误

reactjs - 如何在 Ant Design Form 组件中使用 Google reCAPTCHA?

javascript - Github 页面网站不反射(reflect)本地主机的行为

ionic-framework - IONIC-我无法转换 'image to base64'

javascript - 我必须点击按钮两次才能添加评论

angular - Ionic 4 Angular - 如何自行关闭模态

javascript - 如何根据兄弟组件设置的 URL 重新加载 React 组件?

javascript - 通过react-router更改组件后谷歌recaptcha隐藏

javascript - 在多个组件中重复使用导航栏组件

javascript - react : Does it make sense to pass the whole state to another component?