如何在 React 重定向之前等待事件处理程序的完成
How to await the completion of eventHandlers before redirect in React
我正在用 Redux-React-Realtime 数据库编写一个 Messenger 应用程序。在一个ProfileSearch
页中,有很多MemberCard
。我需要编写一个特定的功能,当我在个人资料页面上单击 MemberCard
上的“消息”按钮时,我将重定向到 Messenger
页面,并使用 channel_id
通过 props
传递给它,将加载与 message_room
.
相关的所有属性
但是,我不确定如何使此交互同步。
目前,在调用消息按钮时,它会在我在 MemberCard
中的操作完全执行之前将我重定向到 Messenger
组件。是否有任何特定的方法来等待事件处理程序的完成,在事件处理程序的某些方法中获取 return 值并将该信息传递给另一个组件并在那里重定向?与其父组件 ProfileSearch
.
不同,子组件 MemberCard
无法访问 this.props.history
这里有一个简短的片段来提供一些背景信息。
ProfileSearch.js
class ProfileSearch extends Component {
constructor(props){
super(props);
this.state = {};
const locals = this.state;
locals[FILTERED_PROFILES] = [];
//pass in searchUser
locals["search"] = "";
}
renderProfiles = (profile) => {
return (
<MemberCard
profile_id = {profile[PROFILE_ID]}
display_name = {profile[PROFILE_PUBLIC_DISPLAY_NAME]}
/>)
}
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const all_profiles = this.props[REDUX_DATA_ALL_PROFILES];
const filtered_profiles = all_profiles.filter((profile) => {
return profile[PROFILE_PUBLIC_DISPLAY_NAME].toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
console.log("Printing filtered");
console.log(filtered_profiles);
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search for profile display name"
icon="search"
onChange={this.onchange}
/>
</div>
<div className="col" />
</div>
<div className="profile-row">
{filtered_profiles.map((profile) => {
return this.renderProfiles(profile);
})}
</div>
</div>
</main>
</div>
);
}
}
MemberCard.js
class MemberCard extends Component {
//console.log(this.props) shows only user, profile_id and display_name
handleSubmit = async (event) => {
try {
event.preventDefault();
//some logic before calling the async function, which does firebase queries
const channel_id = await select_or_create_message_room_method(channel);
console.log(`Channel of uid ${channel_id} created`);
//Passes channel_id to next component and redirect
} catch (error) {
console.log("Error with handleSubmit from MemberCard", error);
}
}
render() {
return (
<Card className={"member"}>
<CardActions>
<Button size="small" color="secondary" onClick={this.handleSubmit} >
<Link to={{
pathname: APP_MESSENGER_PATH,
state: {
//Just testing out the features
postalCode: 1,
hasSubsidy: 2,
subsidyType: 3,
age: 4,
nationality: 5
}
}}
>
<span style={{ color: "white" }}> Message { display_name } </span>
</Link>
</Button>
</CardActions>
</Card>
);
}
}
Messenger.js
class Messenger extends Component {
//TODO: No need for PropTypes since it uses constructor pattern
constructor(props) {
super(props);
this.state = {};
const locals = this.state;
locals[MESSENGER_ACTIVE_CHANNEL_ID] = this.props[MESSENGER_ACTIVE_CHANNEL_ID];//ideally gets the channel_id from the calling component
}
async componentDidMount() {
console.log("Component did mount happen");
if (this.state[MESSENGER_ACTIVE_CHANNEL_ID]) {
//loads everything related to the active channel
}
console.log("Component did mount ended");
}
//TODO:most important, intercept here and change to Redux
//console.log everything here
render() {
//render items
}
}
更新
我意识到我遗漏了一些会影响答案的信息。这是在某些子组件中发生的操作,因此 props.history
可能不会传递到那里。
只需删除 Link
并在 handleSubmit
末尾使用 history.push
handleSubmit = async (event) => {
try {
event.preventDefault();
//some logic before calling the async function, which does firebase queries
const channel_id = await select_or_create_message_room_method(channel);
console.log(`Channel of uid ${channel_id} created`);
//Passes channel_id to next component and redirect
this.props.history.push({
pathname: APP_MESSENGER_PATH,
state: {
//Just testing out the features
postalCode: 1,
hasSubsidy: 2,
subsidyType: 3,
age: 4,
nationality: 5,
},
});
} catch (error) {
console.log("Error with handleSubmit from MemberCard", error);
}
};
要读取 Messenger
组件中的数据,请执行以下操作:
this.props.location.state
编辑 根据评论...
您的 MemberCard
组件理想情况下应该可以访问历史对象,因为您正试图在那里使用 Link
。
无论如何...如果你想在MemberCard
组件中访问历史记录,你有2个选项。
- 对
MemberCard
个组件使用 withRouter。
- 使用custom history object并将其传递给
Router
。这样您的 MemberCard
将可以访问历史对象。
我正在用 Redux-React-Realtime 数据库编写一个 Messenger 应用程序。在一个ProfileSearch
页中,有很多MemberCard
。我需要编写一个特定的功能,当我在个人资料页面上单击 MemberCard
上的“消息”按钮时,我将重定向到 Messenger
页面,并使用 channel_id
通过 props
传递给它,将加载与 message_room
.
但是,我不确定如何使此交互同步。
目前,在调用消息按钮时,它会在我在 MemberCard
中的操作完全执行之前将我重定向到 Messenger
组件。是否有任何特定的方法来等待事件处理程序的完成,在事件处理程序的某些方法中获取 return 值并将该信息传递给另一个组件并在那里重定向?与其父组件 ProfileSearch
.
MemberCard
无法访问 this.props.history
这里有一个简短的片段来提供一些背景信息。
ProfileSearch.js
class ProfileSearch extends Component {
constructor(props){
super(props);
this.state = {};
const locals = this.state;
locals[FILTERED_PROFILES] = [];
//pass in searchUser
locals["search"] = "";
}
renderProfiles = (profile) => {
return (
<MemberCard
profile_id = {profile[PROFILE_ID]}
display_name = {profile[PROFILE_PUBLIC_DISPLAY_NAME]}
/>)
}
onchange = e => {
this.setState({ search: e.target.value });
};
render() {
const { search } = this.state;
const all_profiles = this.props[REDUX_DATA_ALL_PROFILES];
const filtered_profiles = all_profiles.filter((profile) => {
return profile[PROFILE_PUBLIC_DISPLAY_NAME].toLowerCase().indexOf(search.toLowerCase()) !== -1;
});
console.log("Printing filtered");
console.log(filtered_profiles);
return (
<div className="flyout">
<main style={{ marginTop: "4rem" }}>
<div className="container">
<div className="row">
<div className="col">
<Input
label="Search for profile display name"
icon="search"
onChange={this.onchange}
/>
</div>
<div className="col" />
</div>
<div className="profile-row">
{filtered_profiles.map((profile) => {
return this.renderProfiles(profile);
})}
</div>
</div>
</main>
</div>
);
}
}
MemberCard.js
class MemberCard extends Component {
//console.log(this.props) shows only user, profile_id and display_name
handleSubmit = async (event) => {
try {
event.preventDefault();
//some logic before calling the async function, which does firebase queries
const channel_id = await select_or_create_message_room_method(channel);
console.log(`Channel of uid ${channel_id} created`);
//Passes channel_id to next component and redirect
} catch (error) {
console.log("Error with handleSubmit from MemberCard", error);
}
}
render() {
return (
<Card className={"member"}>
<CardActions>
<Button size="small" color="secondary" onClick={this.handleSubmit} >
<Link to={{
pathname: APP_MESSENGER_PATH,
state: {
//Just testing out the features
postalCode: 1,
hasSubsidy: 2,
subsidyType: 3,
age: 4,
nationality: 5
}
}}
>
<span style={{ color: "white" }}> Message { display_name } </span>
</Link>
</Button>
</CardActions>
</Card>
);
}
}
Messenger.js
class Messenger extends Component {
//TODO: No need for PropTypes since it uses constructor pattern
constructor(props) {
super(props);
this.state = {};
const locals = this.state;
locals[MESSENGER_ACTIVE_CHANNEL_ID] = this.props[MESSENGER_ACTIVE_CHANNEL_ID];//ideally gets the channel_id from the calling component
}
async componentDidMount() {
console.log("Component did mount happen");
if (this.state[MESSENGER_ACTIVE_CHANNEL_ID]) {
//loads everything related to the active channel
}
console.log("Component did mount ended");
}
//TODO:most important, intercept here and change to Redux
//console.log everything here
render() {
//render items
}
}
更新
我意识到我遗漏了一些会影响答案的信息。这是在某些子组件中发生的操作,因此 props.history
可能不会传递到那里。
只需删除 Link
并在 handleSubmit
history.push
handleSubmit = async (event) => {
try {
event.preventDefault();
//some logic before calling the async function, which does firebase queries
const channel_id = await select_or_create_message_room_method(channel);
console.log(`Channel of uid ${channel_id} created`);
//Passes channel_id to next component and redirect
this.props.history.push({
pathname: APP_MESSENGER_PATH,
state: {
//Just testing out the features
postalCode: 1,
hasSubsidy: 2,
subsidyType: 3,
age: 4,
nationality: 5,
},
});
} catch (error) {
console.log("Error with handleSubmit from MemberCard", error);
}
};
要读取 Messenger
组件中的数据,请执行以下操作:
this.props.location.state
编辑 根据评论...
您的 MemberCard
组件理想情况下应该可以访问历史对象,因为您正试图在那里使用 Link
。
无论如何...如果你想在MemberCard
组件中访问历史记录,你有2个选项。
- 对
MemberCard
个组件使用 withRouter。 - 使用custom history object并将其传递给
Router
。这样您的MemberCard
将可以访问历史对象。