I was hoping someone could explain to me how I can get the information submitted in my form to show up in a card component? In a way it's a glorified todo list, but I want to know what best practice would be (ie grabbing the data from my database or from the store...?)
import React from 'react';
import { connect } from 'react-redux';
import { saveItem } from '../actions/index';
import { withRouter } from 'react-router-dom';
class AddItem extends React.Component {
render() {
console.log(this.props);
return(
<form onSubmit={(event) => {
event.preventDefault()
const input = {
name: event.target.itemName.value,
price: event.target.itemPrice.value,
description: event.target.itemDescription.value,
userEmail: this.props.currentUser.email
}
this.props.dispatch(saveItem(input))
event.target.itemName.value = ''
event.target.itemPrice.value = ''
event.target.itemDescription.value = ''
}}>
<label>
Item Name:
<br />
<input type="text" name="itemName" />
</label>
<br />
<label>
Price:
<br />
<input type="text" name="itemPrice" />
</label>
<br />
<br />
<label>
Description:
<br />
<textarea type="text" name="itemDescription"/>
</label>
<br />
<button>Submit</button>
</form>
)
}
}
const mapStateToProps = state => ({
currentUser: state.auth.currentUser
});
export default withRouter(connect(mapStateToProps)(AddItem));
so basically I need all of this info to show up in a container when the user hits submit.
These two options have pros and cons, the main differences are:
Using Redux Store:
Refreshing the page will erase all the data stored in your store
The data is in the client, means better performance
Harder to maintain as your apps grows -> store gets nested/larger.
Using Database:
the data is persisted and can be fetched whenever you want
fetching data takes a while and requires an endpoint + server call
much more organized
In general, use your store for temporary data, while your DB for persisting vital data.
In practice, you will find yourself using these methods interchangeably or even both simultaneously. e.g saving a copy of the data in the store before POSTing it into your DB, so the data will be still available for you to display it.
Last tip: https://hackernoon.com/shape-your-redux-store-like-your-database-98faa4754fd5
Related
I have a simple component with an input field and a submit button. I just want to get my data after i fill the input field and submit the form. by using useFetcher hook and fetcher.submit().
import { useEffect } from 'react';
import { useFetcher } from '#remix-run/react'
import { ActionFunction } from '#remix-run/node';
function fetchHook() {
const fetch = useFetcher();
useEffect(() => {
console.log("useEffect");
}, []);
return (
<div>
<h1> Use Fetcher Hook</h1>
<fetch.Form action='/fetcher' method='post'>
<div>
<input type="text" name="name" id="" />
<button type='submit' > Submit</button>
</div>
</fetch.Form>
</div>
)
}
export default fetchHook;
export const action: ActionFunction = async ({ request }) => {
}
What changes should i make to get my desired result. I am new to react-remix.
I'm sure this is a super easy fix, but I'm having an issue where I setup a writable store, and it's mostly reactive, except when a component changes the data, the reactivity in the App file doesn't fire and vice versa. Here's the code:
App.svelte:
<script>
import { data } from './store.js'
import Component from './Component.svelte'
let localData
data.subscribe((value) => {
localData = value;
});
</script>
<h2>In App.svelte</h2>
<p>Hello {localData.name}!</p>
<input name="name" type="text" bind:value={localData.name}>
<p>
{localData.details.number}
</p>
<h2>In Component.svelte</h2>
<Component />
Component.svelte:
<script>
import { data } from './store.js'
let localData
data.subscribe((value) => {
localData = value;
});
</script>
<input type="number" bind:value={localData.details.number}>
<p>Hello {localData.name}!</p>
<p>{localData.details.number}</p>
store.js:
import { writable } from 'svelte/store'
export let data = writable({
name: 'Bob Smith',
details: {
dob: '1982/03/12',
favoriteFoods: ['apples', 'pears', 'bourbon'],
number: 1
},
})
And, if you want to use it in the Svelte REP: https://svelte.dev/repl/164227336d6c4cc29f7ea0a15e89c584?version=3.44.3
You are subscribing to the data and putting it into a local variable and then bind to that. This means the store does not know that anything changed and updates won't be propagated. Two options:
First option: You get rid of the two way binding and update the store explicitely like this:
<script>
import { data } from './store.js'
import Component from './Component.svelte'
let localData
data.subscribe((value) => {
localData = value;
});
function updateName(evt) {
const newName = evt.target.value;
data.update(value => ({...value, name: newName }));
}
</script>
<h2>In App.svelte</h2>
<p>Hello {localData.name}!</p>
<input name="name" type="text" value={localData.name} on:input={updateName}>
<p>
{localData.details.number}
</p>
<h2>In Component.svelte</h2>
<Component />
This is very explicit but also a bit boilerplate-y. We have Svelte's handy auto subscription feature, so let's use that instead. Second and prefered option:
<script>
import { data } from './store.js'
import Component from './Component.svelte'
</script>
<h2>In App.svelte</h2>
<p>Hello {$data.name}!</p>
<input name="name" type="text" bind:value={$data.name}>
<p>
{$data.details.number}
</p>
<h2>In Component.svelte</h2>
<Component />
Notice how we got rid of all the subscription boilerplate. $data accesses the current state of the store and since it's a writable store you can also write back to it that way. You can read more about stores in the docs: https://svelte.dev/docs#component-format-script-4-prefix-stores-with-$-to-access-their-values
I am using angular to create a booking web app using firebase. I am trying to query through the firebase data and filter them to avoid duplicate bookings to be recorded at the same time slots, but I keep getting the error Function Query.where() called with invalid data. Unsupported field value: undefined. I am new to angular and firebase and this is my first project as well. I could really use some help on this.
checkTimeSlot(){
this.formData.date_time = this.formData.bookDate + "_"+ this.formData.timeSlot;
const queryTimeRefUFC = this.afs
.collection("ufc", ref => ref.where("date_time", "==", this.formData.date_time))
.get();
if (queryTimeRefUFC == null){
console.log("true");
return true;
}
else{
console.log("false");
return false;
}}
This is the method in the component.ts where I created the query search. This method is called when the value in the select input changes.
submitBookingUFC() {
this.formData.fullName = this.user.name;
this.formData.userID = this.user.id;
this.formData.date_time = this.formData.bookDate + "_"+ this.formData.timeSlot;
if (this.checkTimeSlot() == true){
alert("The Time Slot you have selected has already been taken. Please select another.");
}
else if (this.checkTimeSlot() == false){
console.log(this.formData.date_time);
this.crudApi.SaveBookingUFC(this.formData);
alert("Record Saved Successfully");
this.ResetFormUFC(); // Reset form when clicked on reset button
} }
This is the method called when the user clicks the submit button.
<div>
<input
type="date"
class="in-bdate"
id="dateUFC"
name="dateUFC"
[min]="today"
max="{{bookMax}}"
value="{{formData.bookDate}}"
[(ngModel)]="formData.bookDate"
#dateUFC="ngModel"
required>
</div>
<div>
<div style="color:red"
*ngIf="dateUFC.errors && (dateUFC.dirty || dateUFC.touched)">
<p *ngIf="dateUFC.errors.required">
<sup>*</sup>Booking Date is required
</p>
</div>
</div>
<div *ngIf="!dateUFC.errors && (dateUFC.dirty || dateUFC.touched)">
<div>
<label for="timesUFC">Time Slot</label>
</div>
<div>
<select
name="timesUFC"
class="in-tslot"
value="{{formData.timeSlot}}"
(change)="checkTimeSlot()"
[(ngModel)]="formData.timeSlot"
#timeSlotUFC="ngModel"
required>
<option *ngFor="let time of timesUFC" >{{time.name}}</option>
</select>
</div>
<div>
<div style="color:red"
*ngIf="(timeSlotUFC.dirty || timeSlotUFC.touched)">
<p *ngIf="timeSlotUFC.errors && timeSlotUFC.errors.required">
<sup>*</sup>Time Slot is required
</p>
<p [ngModel]="timeError" name="error" ngDefaultControl>{{ timeError }}</p>
</div>
</div>
</div>
This is the html code I used to attain the date for the booking and the time of the booking. Using these I created a composite field as date_time using this.formData.date_time = this.formData.bookDate + "_"+ this.formData.timeSlot; to avoid getting duplicate bookings for the same time slot on the same day. The formData here is linked to a class I created for the entire booking array using formData = new UfcData; where UfcData is the name of the class.
export class UfcData {
docID!: string;
userID!: string;
fullName!: string;
contactNo!: string;
timeSlot!: string;
bookDate!: string;
date_time!: string;}
This is the data in the UfcData class.
This is how my Collection and Documents look like
What I need is to acquire the user's input from the form which is acquire from ngModel to the UfcData class and make sure that there aren't any documents in the cloud firestore with the exact same date and time.
*After tweaking the code a little bit the above error does not display. However the if condition in the checkTimeSlot() method always returns true no matter what the option on the select is.
Thanks in advance.
I am new to react and am working on my first project, I have a question on how to connect react with node.js.I have a post page where you can post data and I want to get that data in node.js so that I can connect it with MongoDB.
Here's my code
Post component
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faPlus } from "#fortawesome/free-solid-svg-icons";
import "./componentStyles/postStyles.css";
const element = <FontAwesomeIcon icon={faPlus} />;
function Post() {
return (
<div>
<h2>Post your data here</h2>
<form className="post-form">
<input className="inputTitle" name="title" placeholder="Title" />
<textarea
className="inputContent"
name="content"
placeholder="Content"
rows="3"
/>
<input
className="inputTitle"
name="contact"
placeholder="contact details"
/>
<br />
<br />
<label className="inputTitle" for="CompanyType">
Company Type:{" "}
</label>
<select>
<option value="AI">AI</option>
<option value="Stocks">Stocks</option>
<option value="Finance">Finance</option>
<option value="Medical">Medical</option>
<option value="Engineering">Engineering</option>
<option value="Construction">Construction</option>
</select>
<button className="submitBtn">{element}</button>
</form>
</div>
);
}
export default Post;
Post page
import React from "react";
import Post from "../components/Post";
const Contact = () => {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "90vh",
}}
>
<Post />
</div>
);
};
export default Contact;
Thanks in advance for Answers
There's not one "standard" way of doing this. There are several ways to do it, such as:
using redux and redux middlewares like redux-saga and redux-thunk
with hooks (react-query is worth looking at)
with a simple abstract API manager
directly inside the component (not recommended)
Anyway, React is JavaScript at the end of the day, so you need a client to make HTTP requests to the API. Many use axios.
A pseudo code example:
// APIManager.js
export const getPosts = () => {
return axios.get(`${baseUrl}/posts`).then(resp => resp.data);
};
// Post.jsx
const Post = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
APIManager.getPosts().then(res => setPosts(res));
}, []);
};
Also, there are many other client libraries that you can use for this purpose.
You need to set up a nodejs environment.
Add Express or Koa to handle requests.
Add Mongodb -> use mongo atlas and add the end point to the backend. Make sure to configure your Mongodb Atlas environment to handle requests.
Add the routes that you want to your backend to handle the data exchanges.
Use Fetch or Axios on the front end to get, post, put, delete data.
There are courses and articles that cover this more in detail. I suggest checking them out, because you will need to understand some of nuances that are specific for your use case, such as working with mongodb. This post could be turned into a book, but I just wanted to help guide you in the right direction.
I have a job application form as part of a site built on ServiceStack. I am attempting to use the included ss-utils.js to leverage built-in Fluent Validation, but my form doesn't post the user's file upload. Here's the relevant snippet of the form:
<form id="form-careerapplication" action="#(new CreateCareerApplication().ToPostUrl())" method="post">
<div class="error-summary"></div>
<div class="form-group">
<label>
Upload Resume
</label>
<input type="file" id="Resume" name="Resume" />
<span class="help-block"></span>
</div>
<input type="hidden" name="Id" value="#Model.Id" />
<input type="submit" value="Submit Application" />
</form>
<div id="success" class="hidden">
Thank you for your application.
</div>
$("#form-careerapplication").bindForm({
success: function (careerApplicationResponse) {
$("#form-careerapplication").addClass("hidden");
$("#success").removeClass("hidden");
},
...
Is there something I'm missing in ss-utils.js? Or is there a way of overriding / supplementing the submit behavior to use FormData?
Uploading files via a HTML FORM requires a enctype="multipart/form-data", e.g:
<form id="form-careerapplication" action="#(new CreateCareerApplication().ToPostUrl())"
method="post" enctype="multipart/form-data">
...
</form>
If you want to change support multiple file uploads or change the appearance of the UI Form I recommend the Fine Uploader, there's an example showing how to use Fine Uploader on the HTTP Benchmarks Example.
Whilst Imgur has a simple client HTML and Server example.
Turned out I can use the beforeSend option as part of the configuration passed into bindForm to override the data being sent. Its a bit of a hack, but it worked and I keep the original ss-utils.js fluent validation!
$("#form-careerapplication").bindForm({
success: function (careerApplicationResponse) {
....
},
error: function (error) {
....
},
contentType: false,
processData: false,
beforeSend: function (x, settings) {
var fd = new FormData();
// Tweaked library from https://github.com/kflorence/jquery-deserialize/blob/master/src/jquery.deserialize.js
// Used to translate the serialized form data back into
// key-value pairs acceptable by `FormData`
var data = $.fn.deserialize(settings.data);
$.each(data, function (i, item) {
fd.append(item.name, item.value);
});
var files = $('#form-careerapplication').find("input:file");
$.each(files, function (i, file) {
fd.append('file', file.files[0], file.files[0].name);
});
settings.data = fd;
}
});