How to load data from a different component after submititng form from another component in ReactJs - node.js

I have an Event Model. in my event, people can indicate if they are attending an event by clicking a button, and when they indicate that they are attending an event by clicking a button, a Modal dialog will pop up to ask them if they also want to bring friends along to the event, if they say Yes, it will ask them to choose how many people they want to bring and they will choose from a drop-down list of numbers and submit. after submitting everything it will plus people that are coming and how many people the person is coming with then show them together.
Note: the modal dialog is from another component that I am requiring inside my Event component.
the problem that I am facing now is that my view only updates the people that are coming but doesn't update the number of the people the person is bringing along unless I refresh the page. this was working when I was using class-based-component but after changing my code to function based component it stopped working.
How do I make the browser to update it automatically without refreshing the page?
This is my Sandbox link https://codesandbox.io/s/compassionate-sanne-pmmx6?file=/event-comments.component.js
please use this URL inside sandbox https://pmmx6.csb.app/events/
Just add events after the URL provided by sandbox in other to load the events data because the link to the event is not showing inside the sandbox (I don't know why)

Maybe you can solve this by using event emitter
Use
EventEmitter.subscribe('refresh', (event)=>this.refresh(event))
to create the event
And when you want to execute it you use
EventEmitter.dispatch('refresh', event)
Step by step to create a eventEmitter:
Create a eventEmitter.js file:
const EventEmitter = {
events: {},
dispatch: function (event, data) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(data))
console.log("Dispatched: " + event)
},
subscribe: function (event, callback) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(callback)
console.log("Subscribed: " + event)
},
unsubscribe: function(event) {
if (this.events[event]) {
delete this.events[event]
}
console.log("Unsubscribed: " + event)
}
};
module.exports = {EventEmitter};
In the component you want to refresh first you import the eventEmitter.js. For example:
import {EventEmitter} from "./tools/eventEmitter";
Then you use subscribe() to create a event:
EventEmitter.subscribe('refresh', (event)=>this.refresh(event))
where refresh is the function will execute when you dispatch the event
Finally, when you want to refresh the component, use .dispatch():
EventEmitter.dispatch('refresh', event)
This will execute the this.refresh() first component funcion
If you want to look https://medium.com/#lolahef/react-event-emitter-9a3bb0c719 is a good event emitter's page

Thanks, Everyone, I have solved the problem by just adding events after my API call. I saw the example on the React Facebook page. This method reloads the data anytime there is a change.
const [events, setEventData] = useState([]);
useEffect(() => {
axios
.get(
"https://cryptic-shelf-72177.herokuapp.com/events/" +
props.match.params.id +
"/eventcomments"
)
.then((response) => {
setEventData(response.data);
})
.catch(function (error) {
console.log(error);
});
}, [events]);

Related

What is the proper way to get and display total_unread_count in React?

I'm trying to create a chat icon in a navigation bar with a message count (ala FB, Twitter, etc). I'm using ReactJS. The menu component is separate from the chat components. I'm kind of getting what I want, but not completely. I'm hoping someone can show me the correct way to listen for real time changes to total_unread_count in react.
Right now, if user a sends a new message to user b and user b is not on the chat screen, they will get badge with a message count. I can navigate all around and it'll keep that count. If I click on the chat view to navigate to the chat and click on the channel, then go back to any other screen, the notification count does not change. But, if I refresh the page manually, it'll clear the badge.
So, my expectation is that when a user has viewed the channel, that the state of the chat icon's badge count be updated to reflect that I've seen the message. Having to manually refresh the screen means I'm doing something wrong.
Here's my code so far:
useEffect(() => {
async function init() {
// set state initially because it appers that client.on events only happen a new event.
if (user != null) {
const response: any = await chatClient.connectUser({ id: user.uid }, token)
setUnreadCount(response.me.total_unread_count)
}
// update state when a new event occures.
chatClient.on((event) => {
if (event.unread_channels !== undefined) {
console.log("COUNT: ", event.total_unread_count)
setUnreadCount(event.total_unread_count)
}
})
}
init()
}, [])
I hope I'm communicating this well enough to make sense. I appreciate any help I can get.

How to increase increase database attribute by one by making a get request to the database from Reactjs

I am working on Mernstack. I have a model called Events, the Events have a title, description, startingDate, and closingDate attributes. when an Event is created, people can indicate that they are going for the event by clicking a button and this button will update another attribute inside that Event called going by increasing the number by 1. this was working with Node and Expressjs only but now that I am integrating React to Node, I don't know how to make it work.
Now my question is, how do I make a GET request from React to My Express route, by clicking a link so that the going attribute inside the Event model will be increased by one?
Here is my Event route
router.get("/:id/going", async (req, res, next) => {
Event.findById(req.params.id, function(err, event) {
if (!event) {
return next(new Error('Could not load Document'));
}else {
event.going += 1;
event.save();
res.json(event)
}
});
});
and here is my constructor in Reactjs.
Note: my Event and EventComment is working fine, i am only looking for a way to increase the value of going attribute inside the event by 1 whenever a link clicked.
constructor(props) {
super(props);
this.state = {
eventcomments: [],
event: '',
name: '',
description:'',
going: '',
};
}
the GET request i want to use to trigger the event route to increase the number by 1
axios.get('http://localhost:9000/events/'+this.props.match.params.id+'/going')
.then(res => {
this.setState({
going: '',
})
})
and this is the link i want a user to click for the going attribute in the Event route to increase by 1
<Link to={"/events/"+this.state.event._id+"/going"}>Going</Link>
since your endpoint is returning the updated event record with the updated going property, just set state with that value.
axios.get('http://localhost:9000/events/'+this.props.match.params.id+'/going')
.then(res => {
this.setState({
going: res.data.going
})
})
if res.data.going is how the return value is shaped.
Thanks Guys. I have managed to get it to work.
Here is what I did.
updateGoing = going => {
axios.get('http://localhost:9000/events/'+this.props.match.params.id+'/going')
.then(response => {
his.setState({event: response.data})
});
and Changed it from Link to Button
<button onClick={() => this.updateGoing(this.state.event._id)}> Going </button>

how to refresh page when hitting api endpoint (nuxt.js)

I'm making an app that displays a list of orders. The problem is when I submit a new order by hitting an endpoint with a post request with the data for a new order, the page or the components need to refresh automatically to display this new order. I don't know how this is achieved with nuxt. The client-side HTML rendering needs to be actively reacting to events happening on the server-side.
So, you don't actually need to refresh the page to do this, you can use axios to POST an order and update your page with that particular order
export default {
data(){
return {
newOrder: null
}
},
methods:{
newOrder(){
const newOrder = await this.$axios.post(...)
this.newOrder = newOrder
},
}
}

how will one angular component tell another to refresh without manually refreshing whole page

I have a node backend with firebase auth that connects to an angular frontend. I have two component that is the navbar and the register form, when I register I call a backend function to register in firebase and sent back the firebase.auth().currentUser, how should my angular frontend navbar detects the arrival of such user and updates itself accordingly, without me refresh the page?
I assume this is how your components are structured:
// In app.component.html
<app-navbar></app-navbar>
<router-outlet></router-outlet> // For rest of the pages.
Here, there are 2 ways (I'll not talk about including ngModel) by which we can pass data to navbar for updating the status/data of navbar.
1. Using Input/Output decorators.
// Your navbar.component.ts
// I'm assuming you have set up model for User. If no, then change the type to **any**.
#Input() currentUser: IUser;
// Your navbar.component.html
<p *ngIf="currentUser"> {{currentUser | json}} </p> // Render this if currentUser exists. By default, it is undefined.
Now, in your App component:
//In your app.component.ts
User: any | IUser;
public authenticateUser() {
this.someServiceToAuthenticateUser.subscribe(
res => this.User = res,
error => console.error(error)
);
}
// In your app.component.html
<app-navbar [currentUser]="User"></app-navbar>
<router-outlet></router-outlet>
Using a common service.
You can create the common service which stores the authenticated user in it. From your App component, you can set the user on the success of authenticating the response and from other components, you can fetch the authenticated user.
export class UserService {
private currentUser: IUser | any;
setCurrentUser(userToSet: any) {
this.currentUser = userToSet;
}
getCurrentUser() {
return this.currentUser;
}
Now, in your App component, if the request for authenticating the use is a success, then set the currentUser of UserService:
//In your app.component.ts
User: any | IUser;
public authenticateUser() {
this.someServiceToAuthenticateUser.subscribe(
res => this.UserService.setCurrentUser(res),
error => console.error(error)
);
}
Now, in your navbar component, get the current user from UserService.
// In navbar.component.ts
currentUser: any;
constructor(private userServicce: UserService) {
getuserFromservice();
}
public getuserFromservice() {
setInterval(() => {
curretnUser = this.userService.getCurrentUser()
}, 3000);
Important: In this approach, notice in navbar component, I have set the current user in setInterval. This is because your getuserFromservice() will run only once (when it is created/rendered for the first time) and at this time, userService will have no currentUser. So navbar will never get the currenUser.
If you want to replace the setInterval approach (I highly encourage to replace it), then use Subjects/BehaviourSubject/ReplaySubject. I did not include them here because Rxjs is a huge topic in itself and including it would be too much to understand here.
Input & Output operator is good but It can't provide flexibility of sharing data like observable
Here You need to use Subject Observable to share data among the app. It's very easy and useful thing. You can send signal to all the lisner when user is registered.
What you need to do
1) Create one service file to share data
- service have subject observable. Using that you can subscribe the channel for user data
2) In the your header component listener that service and set the listener coming data to header user data
3) From your register, Profile update,or anywhere else user data was update, just past that data to subject observable it will automatically update user in entire app. follow below example to achieve this
You can find the working demo in below link
https://jasonwatmore.com/post/2019/02/07/angular-7-communicating-between-components-with-observable-subject

how to prevent multiple user input due to refreshes (Node JS)

I am quite new to web development itself. And I have a problem which I have no idea how to solve or even what to google. The web app is developed with Node JS and MySQL.
So let me explain the situation.
On my website you can create and delete posts.
On "/create", the user enters contents for the post.
Then the user clicks the "submit" button, which is routered to "/create_process"(where the data is actually saved in database)
Occasionally there is some delay in loading "/create_process". So the user keeps refreshing while loading. -> Here is the problem. Everytime the user refreshes at this stage same inputs are sent again and again. The result is multiple posts with exactly same contents.
I am sure that there must be a way to block such trivial inputs.
You can have a throttle function on whatever the use is clicking. Example:
const throttle = (func, limit) => {
let inThrottle
return function() {
const args = arguments
const context = this
if (!inThrottle) {
func.apply(context, args)
inThrottle = true
setTimeout(() => inThrottle = false, limit)
}
}
}
from medium article

Resources