简体   繁体   中英

How to pass async props from parent-component to child-component in React

Imagine this simple scenario below in React:

在此处输入图像描述

In this example, we have a single parent component with a child component. When the parent component begins instantiation it needs to make a request to get a childId. The request could or could not be async. In my particular case I'm using electron.

After the parent id retrieves the childId I then want to pass that childId as a prop to the child component which then makes another request to retrieve it's own state.

This is the functionality that I would like to achieve. The issue that I've been wrestling with for the past few hours revolves around the retrieval of the childId. Unfortunately, React creates the child component before the parent component retrieves the childId. Therefore the child component is unable to retrieve it's own state.

I would like to see if there is a way I could delay the child-component from rendering until the parent component retrieves the childId.

ParentComponent

interface IState {
ticketId: number;
}

export class TicketOrchestrator extends React.Component<{}, IState> {
    public state: IState = {
        ticketId:0
    };

public render(): React.ReactNode {
    const onPrevious = () => console.log("FromPrevious");
    const onNext = () => console.log("FromNext");
    return (
    <div> 
        <Ticket ticketId={this.state.ticketId} previous={onPrevious} next={onNext}/>
    </div>
    );
}

public componentDidMount(): void {
    ipcRenderer.on("ticketOrchestrator", this.onMessage);
}

public componentWillUnmount(): void {
    ipcRenderer.removeAllListeners("ticketOrchestrator");
}

private onMessage = (event: any, ticketId: any) => {
    console.log("TicketId", ticketId);
    this.setState({ ticketId: ticketId });
};
}

Child Component

interface IState{
    id: number,
    header: {
        ticketNumber: string,
        title: string,
        date: Date
    },
    body: {
        content: string,
    }
}

interface IProps{
    ticketId: number,
    previous: any,
    next: any
}

export class Ticket extends React.Component<IProps, IState> {
    public state:IState = {
        id: this.props.ticketId,
        header: {
            ticketNumber: "",
            title: "",
            date: new Date()
        },
        body: {
            content: "",
        }
    };

public render(): React.ReactNode {
    const handleClickNext = () => this.props.previous();
    const handleClickPrevious = () => this.props.next();
    return (
    <div>
        <button onClick= {handleClickPrevious} >Previous</button>
        <button onClick= {handleClickNext}>Next</button>
        <div>
            <h2>{this.state.header.title}</h2>
            <h4>{this.state.header.date.toLocaleTimeString()}</h4>
        </div>
        <div>
            <p>{this.state.body.content}</p>
            <p>Id: {this.state.id}</p>
        </div>
    </div>
    );
  }
};

Thanks, Ruben

Assuming your ticketId is always 0 before it has been loaded, you can just show alternative/loading content while your ticketId is 0 :

<div>
  {this.state.ticketId === 0 ? (
    <>Loading...</>
  ) : (
    <Ticket
      ticketId={this.state.ticketId}
      previous={onPrevious}
      next={onNext}
    />
  )}
</div>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM