gpt4 book ai didi

reactjs - Ionic/React/TypeScript,使用react-router history.push, history.replace and history.goBack动画触发两次

转载 作者:行者123 更新时间:2023-12-05 07:07:00 26 4
gpt4 key购买 nike

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

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

如您所见,转换总是发生两次并且在任何地方都找不到解决方案......使用的版本: - 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);

最佳答案

您不能将 componentWillMount 生命周期方法声明为异步。

来自React docs about UNSAFE_componentWillMount()

Avoid introducing any side-effects or subscriptions in this method.
For those use cases, use componentDidMount() instead.

React blog "Update on Async Rendering" (03/2018):

One of the biggest lessons we’ve learned is that some of our legacy component
lifecycles tend to encourage unsafe coding practices. They are:

componentWillMount
componentWillReceiveProps
componentWillUpdate

These lifecycle methods have often been misunderstood and subtly misused;
furthermore, we anticipate that their potential misuse may be more problematic
with async rendering. Because of this, we will be adding an “UNSAFE_” prefix
to these lifecycles in an upcoming release. (Here, “unsafe” refers not to
security but instead conveys that code using these lifecycles will be more
likely to have bugs in future versions of React, especially once async
rendering is enabled.)

Victoria Fluharty 撰写了有用的帖子 componentWillMount() vs componentDidMount()关于那个话题。

tl;dr:如果您有异步逻辑,则需要将其移至 componentDidMount()(或迁移至更现代的方法,例如使用 React hooks 的功能组件|而不是部分弃用的生命周期方法。

您可以将 componentDidMount() 声明为 async,但可能会有一些注意事项:

关于reactjs - Ionic/React/TypeScript,使用react-router history.push, history.replace and history.goBack动画触发两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62298959/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com