how to perform crud operation in react with firebase database - reactjs

I am trying on trial and error basis. I tried to insert username and password in the database using reactjs by event handling, but whenever I enter the username and the password both fields get the same value. For example, if I put 'ABC' as username and 123 as password then the username and password will get same value 123 in the database.
1.trying to insert data using event handling.
class Login extends Component{
ref = firebase.firestore().collection('login');
state = {
username: '',
password: ''
};
handleChange = (event) => {
const state = this.state
state.username = event.target.value;
state.password=event.target.value;
//console.log(state[event.target.username]);
//console.log(state[event.target.password]);
this.setState({username:state.username,
password:state.password });
console.log(state.username);
console.log(state.password);
}
onSubmit = (event) => {
event.preventDefault();
const { username,password } = this.state;
this.ref.add({
username,
password
}).then((docRef) => {
this.setState({
username: '',
password:''
});
this.props.history.push("/")
})
.catch((error) => {
console.error("Error adding document: ", error);
});
}
render()
{
return(
<form onSubmit={this.onSubmit}>
<div className="container mt-5 w-50">
<div className="form-group">
<label for= "user name" className="">User Name:</label>
<input type="text" name="userName" placeholder="UserName" className="form-control w-50" onChange={this.handleChange.bind(this)}/><br/>
<label for="password" className="">Password:</label>
<input type="password" name="password" placeholder="password" className="form-control w-50" onChange={this.handleChange.bind(this)}/><br/>
<button name="Login" className="btn btn-success w-50 mb-3">Login</button><br/>
{/* Don't Have an Account? SignUp */}
<Link to="/signup">Don't Have an Account? SignUp</Link>
</div>
</div>
</form>
);
}
}
export default Login;
username and password should get their actual values.

I believe this is because you are setting the state of both to the same value (event.target.value) in your event handler. You're also mutating state which is not a good thing to do in any situation.
in your handleChange function you are changing username AND password state values to the value of event.target.value which will happen when onChange fires in whichever input you are using handleChange as a listener.
change your handleChange function to this:
handleChange = event => {
let {name, value} = event.target;
this.setState({
[name]: value
});
}
by using {[name]: value} when the event fires in an input with name="password" the password value in your component's state will update
Your render function is a bit confusing but I am going to assume you're rendering a form with labels for username and password...
then in your input within your form (which I can't see in your markdown above, but I'm assuming is in the Login component):
<input name="username" value={this.state.username} onChange={this.handleChange} />
<input name="password" value={this.state.password} onChange={this.handleChange} />

Related

React How do I extract data from a form when triggering onSubmit event?

I am messing around with Riot's API that allows getting information of a player by the player's name. I am trying to get an API key (I only got a 24 hour key) and the target player's name from users' input.
export function PlayerSearch() {
function handlesubmit(e) {
console.log(e.target);
e.preventDefault();
}
return (
<div className='player'>
<div className='inputfield'>
<form onSubmit={handlesubmit} method='GET' autoComplete="off">
<div>
<label htmlFor="key">Your API key:</label>
<input
placeholder='Your API key'
onFocus={(e)=>{e.target.placeholder=''}}
type="text"
id="key"
name="key" />
</div>
<div>
<label htmlFor="name">Player name:</label>
<input
placeholder='Player name'
onFocus={(e)=>{e.target.placeholder=''}}
type="text"
id="name"
name="name" />
</div>
<div>
<input type='submit' />
</div>
</form>
</div>
</div>
);
}
And I got this in the console:
So how exactly do I extract the two inputs from the form?
In addition, is it possible that I can call another component and pass data as props to handle the submitted data so that the code is cleaner?
You should have a state to store your inputs:
const [formData, setFormData] = useState({ key: "", name: "" });
Then you need a function that gets called onChange of your input fields to update your state:
const onChange = (event) => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
And you need to pass that function to your input onChange property:
<input
placeholder="Your API key"
onFocus={(e) => {
e.target.placeholder = "";
}}
type="text"
name="key"
value={formData.key}
onChange={onChange}
/>
Then you can access the state in your handleSubmit:
function handlesubmit(e) {
console.log(formData);
e.preventDefault();
}

How to add n number of emails in react?

I have created a user registration form which contains of firstname,lastname,email etc.
Here a user can add n number of emails.For this,I have created a button and onClick it should open the input field.
<--Here is the code -->
const [formData, setFormData] = useState({
firstname: "",
lastname: "",
email: "",
})
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const newStudent = {
firstname,
lastname,
email,
}
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newStudent);
await axios.post(`http://localhost:5000/student`, body, config);
}
const handleClick = () => {
return <Input type="email" name="email" value={email} onChange={handleChange} />
};
return (
<Form className={classes.root} onSubmit={handleSubmit}>
<div>
<Input
id="standard-multiline-flexible"
label="First Name"
multiline
name="firstname"
value={firstname}
onChange={handleChange}
/>
</div>
<div>
<Input
id="standard-multiline-flexible"
label="Last Name"
name="lastname"
value={lastname}
onChange={handleChange}
multiline
/>
</div>
<div>
<Input
id="standard-multiline-static"
type="email"
label="Email"
name="email"
onChange={handleChange}
value={email}
multiline
/>
<button className="btn btn-primary" onClick={handleClick}>
Add
</button>
<PrimaryButton>Submit</PrimaryButton>
</Form>
)
Can anyone tell me how should I define the handleClick() so that whenever I click the add button,it renders a new Input field?
Another way you could achieve this if you want the user to see their input emails remove them etc is to do the following:
Create an emails state array.
Add an email text field with an add button next to it.
When the user enters an email and presses add, add that email to the array.
You can then map the array to show the added emails as a list with the option to delete the emails if the user decides to.
At the end of handle click
Instead of doing this
return <Input type="email" name="email" value={email} onChange={handleChange} />
Do this ->
setFormData({firstname: "",lastname: "",email: ""});
Edits
You can display the emails via a list after making the API call
You can have a delete button to delete that email from the list.
"There are n ways to implement. Please be more specific"

input filld not getting while typing

in input tag while i placed value attribute in it it not getting input from keybord not showing input
import React from 'react'
class Postform extends React.Component {
state = {
name: 'helo',
email: '',
password: '',
bio: '',
};
changeHandler = (event) => {};
submitHandler = (event) => {
event.preventDefault();
};
render() {
return (
<div className="container">
<form onSubmit={this.submitHandler}>
<div classNam=" form-group ">
<label htmlFor="name">Enter your name </label>
<input
placeholder="Enter your name"
id="name"
className="form-control"
name="name"
onChange={this.changeHandler}
value="hello"
/>
</div>
<button type="submit" className="btn btn-info">
submit
</button>
</form>
</div>
);
}
}
export default Postform;
You set the input value to be hello this means that it will stay hello no matter what.
To make the input value dynamic you going to need to set the value from the state of your component as the input value.
This means that you also going to have to update the state when the input value changes using the changeHandler.
Lets start from the input
// Always read the input value from state
// and when the input value changes call this.changeHandler
<input onChange={this.changeHandler} value={this.state.name} />
Then the changeHandler
changeHandler = (event) => {
// The input value has been changed, get the value from
// event.target.value and set it as state.
this.setState({ name: event.target.value });
};
Now the state will be updated and the component will re-render the input with the current state.name as the value

Form.Control type password in React-Bootstrap always renders an default password that i can't remove

I am doing the login page and i realized i cannot set the default values of the Form.Control type password input!!!
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: 'thisIsMyDefaultPassword',
isLoading: false,
redirectToReferrer: false
};
}
handleChange = name => event => {
let update = {};
update[`${name}`] = event.target.value;
this.setState(update);
}
handleFocus = () => {
this.setState({ password: '' });
}
handleSubmit = () => event => {
let data = {
email: this.state.email,
password: this.state.password
}
this.props.login(data)
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate');
let { currentUser } = this.props;
console.log('currentUser ', currentUser, 'prevProps.currentUser ', prevProps.currentUser );
if (JSON.stringify(prevProps.currentUser) !== JSON.stringify(currentUser)) {
console.log('currentUser !=');
if (currentUser._id) {
this.setState({
redirectToReferrer: true
})
}
}
}
render() {
let { email, password , isLoading, redirectToReferrer } = this.state;
console.log('password when rendered', password);
if (redirectToReferrer) {
return <Redirect to={'/'} />;
}
return (
<div className="loginWrapper">
<div className="loginContainer">
<Form>
<Form.Group controlId="formGroupEmail">
<Form.Label>Email Address</Form.Label>
<Form.Control
type="email"
value={email}
onChange={this.handleChange('email')}
placeholder="Enter Email"
/>
</Form.Group>
<Form.Group controlId="formGroupPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
defaultValue={this.state.password}
onFocus={this.handleFocus}
onChange={this.handleChange('password')}
placeholder="Password"
/>
</Form.Group>
</Form>
<Button
variant="primary"
size="lg"
disabled={isLoading}
onClick={this.handleSubmit()}
block
>
{isLoading ? 'Loading…' : 'LOGIN'}
</Button>
</div>
</div>
);
}
}
i expect the default values rendered to be controlled by the default state of my component. But it just don't work. I have tried defaultValue / value / and defaultValue with value. but there is still this default number being rendered in the password input .. The above are my latest codes i am still facing the problem although i crack it with onFocus. If there's any better improvement to my codes please comment below too. An Advance thank you to all commenters. really appreciate the help of this community.
Below are the console logs for console.log('password when rendered', password) IT shows that react-bootstrap javascript is clearning the password and setting as 0346:
password when rendered thisIsMyDefaultPassword
Login.js:51 password when rendered
Login.js:51 password when rendered 0346
Thus concluding that the defaultValue for the type password does not work ?
The value props is too much here, if you get rid of it, you can change the input.
Additionally, you always provide the string "password" to your onChange handler as a value. This might not be what you want to do, but instead using the actual password the user is entering.
In your render method:
<p>Current password: {this.state.password}</p>
<Form>
<Form.Group controlId="formGroupPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
defaultValue={this.state.password}
onChange={this.handleChange('password')}
placeholder="Password"
/>
</Form.Group>
</Form>
And your handleChange function could look like:
handleChange = name => event => {
this.setState({ password: event.target.value });
};
Example: https://codesandbox.io/s/8x8zw28nv2
There are two type of valued components(TextField, Checkbox, etc.):
Controlled - The component whose value is controlled by the code implementation. In this type of component you have to set value prop of the component with the value source and handle it's onChange to get the value and update in the future source.
<TextField value={this.state.password}
onChange={(event) => this.setState({ password: event.target.value })}
/>
Un-controlled - The component which has a default value and that value can changed without any trigger/handling in the component code. These components have a prop 'defaultValue' populated with the initial value you want to assign.
<TextField defaultValue={this.state.password} />
You can't use both value and defaultValue on same component.
In your case You have to remove defaultValue prop, as you need a controlled component to make its value persist.
You have the same value for defaultValue and value, seems like it doesn't make sense because if value has a value, that value will be rendered. Try matching defaultValue to another value or just remove defaultValue.
Does your onChange work? Seems like not. Are you implemented your handleChange? Because you are using controlled inputs.
Try this:
handleChange = e => {
this.setState({
password: e.target.value
})
}
<Form>
<Form.Group controlId="formGroupPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
value={password}
onChange={this.handleChange}
placeholder="Password"
/>
</Form.Group>
</Form>

Submitting redux form values

I am new to react and redux technology. now started building an application that contains several redux forms. We want to submit simple form with values.
For ex: login form
Username : text input field
Password: text input field
Submit button
After entering values in fields and click on submit button i want to get the username and password field values in object or json data .. so that I can store it to my server with POST method.
Right now we are using handleSubmit(), but data is not coming as object
1 - The best practice to deal with input values are making them controlled. Which means :
Instead of
<input type='password' />
You do :
<input
type='password'
value={password}
onChange={ event => myInputHandler( event.target.value ) }
/>
The value might come from your state, redux state or as a props etc.
Your handler function differs according to where you store it.
I will give you an example with react state :
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
So whenever someone types, your onChange handler will be called, so that your react state will update with the input ( event.target.value ).
2 - If you need these values when a user submits, then you need to wrap these input fields within a form element and attach a onSubmit handler.
onSubmitHandler( event ){
event.preventDefault()
let password = this.state.password
// use password or other input fields, send to server etc.
}
<form onSubmit={ event => this.onSubmitHandler(event) }>
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
</form>
Hope you get what you need.
If you are using redux to store state then use redux-from then use redux from
import React from 'react'
import {Field, reduxForm} from 'redux-form'
const SimpleForm = props => {
const {handleSubmit, submitting} = props return (
<form onSubmit={handleSubmit(e=>console.log('your form detail here', e))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name" />
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
</div>
</form>
) }
export default reduxForm({ form: 'simple'})(SimpleForm)
Go here for more detail
https://redux-form.com
I put the name of the input as the key that I want to use.
Then each time the input changes I destructure the event passed to the onChange function, and I use the name,value to update the state.
On form submit make sure to use preventDefault(); in order to avoid the page refreshing.
import React, { Component } from 'react'
class FormExample extends Component {
constructor(props){
super(props)
this.state = {
formData: {}
}
}
handleInputChange = ({ target: { name,value } }) => {
this.setState({
formData: {
...this.state.formData,
[name]: value
}
})
}
handleFormSubmit = e => {
e.preventDefault()
// This is your object
console.log(this.state.formData)
}
render() {
return(
<div>
<Form
handleSubmit={this.handleFormSubmit}
handleChange={this.handleInputChange}
/>
</div>
)
}
}
const Form = ({ handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} name="username" type="text" placeholder="Username" />
<input onChange={handleChange} name="password" type="password" placeholder="Password" />
<button>Submit</button>
</form>
)
export default FormExample

Resources