I am writing a Messenger Application with Redux-React-Realtime databases. In a ProfileSearch
page, there are many MemberCard
. I need to write a particular feature where upon clicking the “message” button on a MemberCard
while I’m technically on a profile page, I will redirect to the Messenger
page, and with the channel_id
that is passed to it via props
, will load up all attributes related to the message_room
.
However, I’m not sure how to make this interaction synchronized.
Currently, upon calling the message button, it redirects me to the Messenger
component before my action in the MemberCard
gets completely executed. Is there any particular way to await the completion of the eventHandler, get the return value inside some method of the event handler and pass that information to another component and redirecting there? The child component MemberCard
does not have access to this.props.history
unlike its parent ProfileSearch
.
Here's a short snippet to give some context.
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
}
}
Update
I realised I left out some information which will affect the answer. It's an action that occurs in some child component, so the props.history
may not be passed there.
Just remove Link
and use history.push
at the end of handleSubmit
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);
}
};
To read data in Messenger
component, do this:
this.props.location.state
Edit Based on comment...
Your MemberCard
component ideally should have access to history object as you are attempting to use Link
over there.
Anyway ... If you want to access history in MemberCard
component, you have 2 options.
MemberCard
component.Router
. This way your MemberCard
will have access to history object.