post request without a form or a button in React? - javascript

So I have to make a post request without a form or a button. I have the patientInfo array that is rendered on a table. When the user chooses a location for a patient, then that patient will have a timestamp value. When the patient in the array has a timestamp that's when I am supposed to auto post the patient with the timestamp.
My handleAutoObsSubmit() is kinda working but the problem is, it maps over the patienArray and sends the patient multiple time so if the user chooses the third patient's location, there will be three object of the same patient that is sent.
Another issue I am having with is componentDidUpdate, it sends the post request every second. I suspect that is because the patient count is being count down every sec. Not 100% sure though. Is it even a good idea to send post request in componentDidUpdate?
patientInfo = [
{ count: 100, room: "1", name: 'John Nero', timeStamp: '', location: ''},
{ count: 100, room: "2", name: 'Shawn Michael', timeStamp: '', location: ''},
{ count: 100, room: "3", name: 'Gereth Macneil', timeStamp: '', location: ''}
]
handleAutoObsSubmit = () => {
const postUrl = '/send_patient_that_has_timeStamp';
const timeStampedPatients = this.state.patientInfo.filter(patient => patient.timeStamp !== '');
let data = {};
timeStampedPatients.map((patient) => {
data = {
room: patient.room,
patient: patient.name,
timestamp: patient.timeStamp,
location: patient.locationInfo,
};
});
fetch(postUrl, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
})
.then((res) => {
if (!res.ok) {
console.log('request failed');
} else {
console.log('request sent');
}
});
}
componentDidUpdate() {
this.state.patientInfo.map(patient => {
if (patient.timeStamp !== '') {
this.handleAutoObsSubmit();
}
});
}
componentDidMount() {
this.countDownInterval = setInterval(() => {
this.setState(prevState => ({
patientInfo: prevState.patientInfo.map((patient) => {
if (patient.locationInfo!== '') {
if (patient.count <= 0) {
clearInterval(this.countDownInterval);
}
return { ...patient, count: patient.count - 1 };
}
return patient;
})
}));
}, 1000);
}

You should be able to handle it in a similar fashion to this:
function Table() {
const [tableData, setTableData] = React.useState([
{
name: "John Doe",
timestamp: ""
},
{
name: "Jane Doe",
timestamp: ""
},
{
name: "Nancy Doe",
timestamp: ""
}
]);
const updateItem = (event, index) => {
let newstate = [...tableData];
newstate[index].timestamp = (new Date(Date.now())).toString();
alert(`Do POST here: ${JSON.stringify(newstate[index],null,2)}`);
setTableData(newstate);
};
return (
<table border="5">
<tr>
<th>
<div>Patient</div>
</th>
<th>
<div>Timestamp</div>
</th>
<th>Update</th>
</tr>
{tableData.map((item, index) => {
return (
<tr>
<td>{item.name}</td>
<td style={{width:'410px'}}>{item.timestamp}</td>
<td>
<button
style={{backgroundColor:'green', color:'white'}}
onClick={event => updateItem(event, index)}>
UPDATE
</button>
</td>
</tr>
);
})}
</table>
);
}
ReactDOM.render(<Table />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>

Related

Type script type from prev

I'm not sure which type to designate here.
"HowitterObject" in setHowitters is data and "...prev' is the continuous addition of data from howitterObject.
interface IhowitterMessage {
message: string;
createAt: number;
id: string;
}
const Home = () => {
const [howitters, setHowitters] = useState<IhowitterMessage[]>([]);
const getHowitters = async () => {
const dbHowitter = await dbService.collection("howitter").get();
dbHowitter.forEach((document) => {
const howitterObject = {
...document.data(),
id: document.id,
};
setHowitters((prev: ???) => [howitterObject, ...prev]); //What should I put in the "prev" type?
});
};
useEffect(() => {
getHowitters();
}, []);
return(
<div>
{howitters.map((howitter: IhowitterMessage) => (
<div key={howitter.id}>
<h4>{howitter.message}</h4>
</div>
))}
</div>
);
};
If you console.log(howitters), it is as follows.
(3) [{...}, {...}, {...}]
0: {message: "no", createAt: 1631367025550, id: "q2d9TTgh36mgFZwMQ5EA"}
1: {createAt: 1631365463319, message: "Good", id: "nCABFp1v3dP73gIbckpp"}
2: {message: "hey", createAt: 1631367021665, id: "dmNBa6C8NwhDQDYDOP36"}
It's similar to your state's type
Because prev is your previous state of howitters so you could put IhowitterMessage[] there too:
setHowitters((prev: IhowitterMessage[]) =>

Laravel: Redirect with flash message after submitted form using vue.js

I have two components: Index and Create. Both of these components are loaded from different blade files. The problem is I cannot pass flash message as a prop since these are in different files. How to redirect after a submitted form has been created and and receive the flash message in component Index from Create?
public function store(Request $request)
{
Service::create([
'name' => $request->get('name'),
'vendor_id' => $request->get('vendor'),
'desc' => $request->get('desc'),
'hours' => $request->get('hours'),
'price_per_hour' => $request->get('price'),
'fixed_price' => $request->get('fixed_price'),
'user_id' => $request->user()->id
]);
if (\request()->wantsJson()) {
return response()->json([
'alert_store' => 'New service added successfully.'
]);
}
}
Create component:
if(ok) {
axios.get('/sanctum/csrf-cookie').then(response => {
axios.post('/api/services', {
name: this.form.name,
vendor: this.form.vendor,
desc: this.form.desc,
hours: this.form.hours,
price: this.form.price,
fixed_price: this.form.fixed_price,
})
.then(response => {
this.alert_store = response.data.alert_store
alert(this.alert_store)
window.location.href = '/admin/services';
})
.catch(function (error) {
console.log(error);
});
});
}
},
index.vue:
import Create from './Create.vue';
import Alert from '../Alert.vue';
export default {
props: ['alert_store'],
components: {
Create,
Alert,
},
data(){
return {
services: [],
alert_success: '',
alert_error: '',
errors: [],
success: [],
form: {
name: '',
desc: '',
hours: '',
price_per_hour: '',
vendor: '',
fixed_price: '',
},
selected: null,
}
},
mounted() {
this.loadServices()
this.getStatus()
},
methods: {
loadServices: function(){
axios.get('/api/getservicedata')
.then(response => {
this.services = response.data;
})
.catch(function(error){
console.log(error);
});
},
// getStatus(){
// axios
// .post('/api/services')
// .then(response => {
// console.log(response.data.alert_store)
// });
// },
isEditable(service)
{
this.form.name = service.name
this.form.desc = service.desc
this.form.hours = service.hours
this.form.price_per_hour = service.price_per_hour
this.form.vendor = service.vendor.id
this.form.fixed_price = service.fixed_price
if(service.isEditing)
{
this.selected = service.id
service.isEditable = false
}
this.$set(service, 'isEditing', true)
},
editService(service)
{
if(confirm('Are you sure?'))
{
axios.post(`/api/services/${service.id}`, {
_method: 'patch',
name: this.form.name,
vendor: this.form.vendor,
desc: this.form.desc,
hours: this.form.hours,
price_per_hour: this.form.price_per_hour,
vendor: this.form.vendor,
fixed_price: this.form.fixed_price
})
.then(response => {
this.alert_success = response.data.alert_update
this.success.push(Alert)
this.loadServices()
})
.catch(response => {
this.errors.push(Alert)
this.alert_error = `Could not edit, ${service.name}, from services!`
})
}
},
deleteService(service)
{
if(confirm('Are you sure?'))
{
axios.get('/sanctum/csrf-cookie').then(response => {
axios.delete(`/api/services/${service.id}`, {
__method: 'DELETE'
})
.then(response => {
this.alert_success = response.data.alert_delete
this.success.push(Alert)
this.loadServices()
})
.catch(response => {
this.errors.push(Alert)
this.alert_error = `Could not delete, ${service.name}, from services!`
})
});
}
}
}
}
You could pass props into index.vue component with different ways.
First and properly (on my mind) way is to use session data.
Like:
public function store(Request $request)
{
Service::create([
'name' => $request->get('name'),
'vendor_id' => $request->get('vendor'),
'desc' => $request->get('desc'),
'hours' => $request->get('hours'),
'price_per_hour' => $request->get('price'),
'fixed_price' => $request->get('fixed_price'),
'user_id' => $request->user()->id
]);
\request()->session()->put('yourawesomekey','value');
if (\request()->wantsJson()) {
return response()->json([
'alert_store' => 'New service added successfully.'
]);
}
}
And when you initialize your component in blade file:
...
<your-component-name alert_store="{{ session('yourawesomekey', 'default-value') }}" />
...
NOTE Don't forgot to cleanup session data \request()->session()->forget('yourawesomekey');
Hope it will work for you.

not sending nested params with the put request

I am working on a rails app with vue on front end. I am making a put request to the server. I am not able. to figure out if there is a way of not sending the nested params with the put request like the location and numbers. I just want to send the agency_unique_number and name params on the submitAgency request. Please help me find a way.
export default {
data: function () {
return {
agency: {
name: '',
location: {
street: ''
city:''
province:''
}
numbers: {
office_number: '',
fax_number: ''
}
agency_unique_number: ''
}
}
method: {
submitAgency() {
this.$axios.put('/agency.json', { agency: this.agency })
.then(response => {
})
},
}
}
Simply extract the data you want to send.
export default {
data: function () {
return {
agency: {
name: '',
location: {
street: ''
city:''
province:''
}
numbers: {
office_number: '',
fax_number: ''
}
agency_unique_number: ''
}
}
method: {
submitAgency() {
const { agency_unique_number, name } = this.agency
const data = { agency_unique_number, name }
this.$axios.put('/agency.json', { agency: data })
.then(response => {
})
},
}
}
Please try again with
export default {
data: function () {
return {
agency: {
name: '',
location: {
street: ''
city:''
province:''
}
numbers: {
office_number: '',
fax_number: ''
}
agency_unique_number: ''
}
}
method: {
submitAgency() {
const { name, agency_unique_number } = this.agency
this.$axios.put('/agency.json', { agency: { name, agency_unique_number })
.then(response => {
})
},
}
}

Displaying Fetch Data and Rendering - React JS

I am able to save data into my database. However, i want to know how to show/render the fetch data on my screen after i run my fetch request.
When i add data i am able to push to render on my page. But what i want is, once i run my fetch data function, how do i render the response that i get onto my screen ?
My Json data after fetch looks like this when i console.log(json.data.shipping)
0: { name: "Samsung A10", phone: "001-2342-23429"}
1: {name: "Iphone Xs", phone: "001-12193-1219"}
PS: Beginner with React JS
Below is how i save data
state = {
shippings: userData,
addNewData: {
name: '',
phone: ''
},
};
addData() {
const { name,phone} = this.state.addNewData;
if (name!== '' && phone = "") {
let newData = {
...this.state.addNewData,
id: new Date().getTime()
}
let shippings = this.state.shippings;
fetch( 'http://facicla:5000/api', {
method:'post',
/* headers are important*/
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
body: JSON.stringify(this.state.addNewData)
})
.then(response => {
return response.json();
shippings.push(newData);
NotificationManager.success('Sucess!');
})
}
}
userData
export default [
{
name: 'Shipping-Car',
phone: '001-72342-2342',
} ]
Fetch Data
fetchAllData(){
return this.fetchPost().then(([response,json]) => {
if(response.status === 200)
{
console.log(json.data.shipping)
0: { name: "Samsung A10", phone: "001-2342-23429"}
1: {name: "Iphone Xs", phone: "001-12193-1219"}
}
})
}
fetchPost(){
const URL = 'http://facicla:5000/api';
return fetch(URL, {method:'GET',headers:new Headers ({
'Accept': 'application/json',
'Content-Type': 'application/json',
})})
.then(response => Promise.all([response, response.json()]));
}
Render
render() {
const { shippings, addNewData} = this.state;
return (
<div className="wrapper">
<div className="row row-eq-height">
{shippings.map((shipping, key) => (
<div className="col-sm-3 col-md-3 col-lg-3" key={key}>
<div className="d-flex justify-content-between">
<h5 className="fw-bold">{shipping.name}</h5></a>
<h5 className="fw-bold">{shipping.phone}</h5></a>
</div>
</div>
))}
</div>
}
Try this:
fetchAllData(){
return this.fetchPost().then(([response,json]) => {
if(response.status === 200)
{
console.log(json.data.shipping)
this.setState(
{ shippings: Object.values(json.data.shipping)
//or shippings: json.data.shipping
}
)
//0: { name: "Samsung A10", phone: "001-2342-23429"}
//1: {name: "Iphone Xs", phone: "001-12193-1219"}
}
})
}

How to attach data from local JS file to state in ReactJS?

I am having trouble understanding how to access the data from a local JS file. I have read the React documentation up and down, but I'm stuck on this problem. There must be a flaw in my state/prop logic?
import announcementData from "./AnnouncementData.js"
class Detail extends Component {
constructor(props) {
super(props);
this.state = {
announcement: [
{
id: 0,
...
}
async fetchDetails(id) {
let response = announcementData;
this.state.announcement.map(response, (value, key) => {
this.setState({
[value]: key
}).catch(error => {
this.setState({
error: error.message
});
});
});
}
async componentDidMount() {
const { match } = this.props;
await this.fetchDetails(match.params.id);
}
render() {
const detail = {
id: this.state.announcement.id,
title: this.state.announcement.title,
site_id: this.state.announcement.site_id,
content: this.state.announcement.content,
status: this.state.announcement.status,
scheduled_at: this.state.announcement.scheduled_at,
created_at: this.state.announcement.created_at,
categories: this.state.announcement.categories,
members: this.state.announcement.members
};
return (
<div>
<ListGroup>
<Announcement
id={detail.id}
title={detail.title}
site_id={detail.site_id}
content={detail.content}
status={detail.status}
scheduled_at={detail.scheduled_at}
created_at={detail.created_at}
categories={detail.categories}
members={detail.members}
/>
</ListGroup>
</div>
);
}
}
const Announcement = ({id, title, site_id, content, status, scheduled_at, created_at, categories, members}) => {
return (
<div>
<ListGroupItem>ID: {id}</ListGroupItem>
<ListGroupItem>Title: {title}</ListGroupItem>
<ListGroupItem>Site ID: {site_id}</ListGroupItem>
<ListGroupItem>Content: {content}</ListGroupItem>
<ListGroupItem>Status: {status}</ListGroupItem>
<ListGroupItem>Scheduled at: {scheduled_at}</ListGroupItem>
<ListGroupItem>Created at: {created_at}</ListGroupItem>
<ListGroupItem>Categories: {categories}</ListGroupItem>
<ListGroupItem>Members: {members}</ListGroupItem>
</div>
);
};
export default Detail;
I'm trying to publish the details from an array from a local file (for now) to be displayed by the UI. With this minimal code, I am able to display the "Announcement" function with no data, like so:
ID:
Title:
Site ID:
Content:
Status:
Scheduled at:
Created at:
Categories:
Members:
I need to display the actual data coming from the .js file.
It should be a very basic problem but I am a beginner. Any help is appreciated. Thanks!
AnnouncementData.js:
const announcementData = [
{
id: 0,
title: "John Doe",
site_id: "my business",
content: "I have a new business!",
status: true,
created_at: "14/03/2019",
updated_at: "24/04/2019",
categories: [{ id: 0, name: "John Doe" }],
members: [{ id: 1, name: "Jane Doe", photo_url: "jane.png" }]
},
export default announcementData;
You should change your fetchDetails function to something like this:
async fetchDetails(id) {
this.setState({
announcement: announcementData.find(v => v.id === id)
});
}

Categories