How to display submitted form data in same page in Reactjs? - reactjs

I am new in reactjs. I want to submit form data in same page in reactjs. I am using array to store data but array stores data in one-dimensional and I want it in multi-dimentional form. How can I do that? I am using push() function and there are 5 input field in my form.
Here is my code:
var data = [{}];
export default class Form extends React.Component {
state = {
firstName: "",
lastName: "",
username: "",
email: "",
password: ""
};
change = e => {
this.props.onChange({ [e.target.name]: e.target.value });
this.setState({
[e.target.name]: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
console.log(this.state);
data.push(this.state.firstName,this.state.lastName,this.state.username,this.state.email,this.state.password);
document.getElementById('hello').innerHTML = data;
};
render(){
//form input fields
}
}
Thank You.

Set all your form data values in a state object.
Once, submitted you can set all those values in your state and then you can view the updated state with your form data in the render method.
Something on the lines of
handleSubmit(data) {this.setState({formData: data})}
And then in your render you can view it as
render() { console.log(this.state.formData); return(...); }
Manipulate this variable as you want it now. Care needs to be taken that this state will be null/empty/undefined as per your declaration before the first submit.

Related

React app, after getting data from initial get request, onChange doesnt work

constructor (props) {
super(props)
this.state = {
AyarAdi: '',
Bilgi: '',
FirmaKodu: '',
icerik: {
smsUser: '',
smsApi: '',
mesajAciklama: '',
password: ''
},
errors: {}
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
componentDidMount () {
this.props.AyarlarListesiAl(this.props.user.userCreds.FirmaKodu)
}
handleChange (event) {
this.setState({
icerik: {
...this.state.icerik,
[event.target.name]: [event.target.value]
}
})
}
render(){
<div>
<InputGroup className='mb-3'>
<FormControl
name='password'
placeholder='SMS Şifre'
onChange={this.handleChange}
value={
this.props.data.AyarlarListesi[0] !== undefined
? JSON.parse(this.props.data.AyarlarListesi[0].Bilgi).password
: this.state.icerik.password
}
style={{ maxWidth: 400, height: 40 }}
/>
<span style={{ color: 'red' }}>
{this.state.errors['password']}
</span>
</InputGroup>
</div>
}
const mapStateToProps = state => ({
user: state.user,
data: state.data
})
....
The problem is, in componentDidMount, I send a get request to the server via Redux action, and it gets me data from the redux reducer state; AyarlarListesi. I wanted to fetch the data to the input elements value, So when a user opens the page, he/she can update the previous data just changing it on the input and clicks to submit. I can successfully put the data to the input but I can't change the value of the input, it stays stable, the handleChange function doesn't work. How can I make it work?
Your handleChange function only manipulates the state. However the value to be displayed comes preferrably from props and only if the props field is not available it will fall back to the state variable.
To display the state variable after changing it via user input, you could either swap the condition and make it so the state variable will be displayed unless it's empty (and use the props variable as a fallback) or you could instead update the state variable initially when you get new props.
Assuming you never change props from outside or don't care about later updates, this would be my preferred way of solving your problem:
componentDidMount () {
this.props.AyarlarListesiAl(this.props.user.userCreds.FirmaKodu);
if (this.props.data.AyarlarListesi[0] !== undefined) {
this.setState({
icerik: {
...this.state.icerik,
password: JSON.parse(this.props.data.AyarlarListesi[0].Bilgi).password,
},
});
}
}
Also in your FormControl skip checking if the props data is set and instead always use this.state.icerik.password as the value.
If your props from outside could change and you'd like to restart whenever a new password or AyarlarListesi is passed from outside, you should update the state in componentDidUpdate again:
componentDidUpdate (prevProps) {
if (prevProps.data.AyarlarListesi !== props.data.AyarlarListesi && props.data.AyarlarListesi[0] !== undefined) {
this.setState({
icerik: {
...this.state.icerik,
password: JSON.parse(this.props.data.AyarlarListesi[0].Bilgi).password,
},
});
}
}

React: Permanently store user input as the value

I currently have the user input being updated by state and stored as the value however whenever the user directs to another page, closes the page or refreshes it, the value disappears. I want to permanently store the value there until the user changes their input.
Would I need to use persistent state for this? How can I permanently store the value of the user input until the user changes it?
class Planning extends React.Component {
constructor() {
super()
this.state = {
title: '',
goal: '',
tech: '',
features: '',
details: ''
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
})
}
handleSubmit(event) {
const {
title,
goal,
tech,
features,
details
} = this.state;
event.preventDefault();
this.setState({ title, goal, tech, features, details });
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<label className="label-title">
Project Title:</label>
<input name="title" id="title" type="text" value={this.state.title} onChange={this.handleChange} required aria-required="true"/>
</div>
Change your handleChange function to:
handleChange(event) {
const { value, name } = event.target
localStorage[name] = value
this.setState({
[name]: value
})
}
and your constructor to:
constructor() {
super()
this.state = {
title: localStorage["title"],
goal: '',
tech: '',
features: '',
details: ''
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
This is not very elegant but will work. Alternatively you can save to localStorage on unmount.
Yes, you would have to manage this with a state management lib. Localstorage is too extreme. Plus the state management will come handy for other stuff in your app as it grows so i suggest you start right. You can look at mobx or redux.
Saving to localStorage is a synchronous operation , so we don't need to sync the local state to localStorage every time state variable changes as React already keeps the track of the application state in the user's session . You need to persist it in localStorage when user leaves page / refreshes. Save to localStorage on componentWillUnmount and window.onbeforeunload events. There is the a storage component that handles everything : https://github.com/ryanjyost/react-simple-storage

Reacjs/Graphql: Pass variables values to query from event

So the code below is updating the state of inputValue but for some reason that value is not be passed to the query as the following error is shown:
[GraphQL error]: Message: Variable "$timestamp" of required type "Float!" was not provided., Location: [object Object], Path: undefined
So my question is how do I assign the inputValue to timestamp and pass timestamp to the getObjectsQuery?
class Calendar extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = event => {
event.preventDefault();
console.log(this.state.inputValue);
this.setState({
inputValue: new Date(document.getElementById("time").value).valueOf()
}); //Parent component contains submit button and there lives state. Submit handler should only set value in state with...setState()- NOT directly
this.props.data.refetch({
//For some reason
timestamp: this.state.inputvalue
});
console.log(this.state.inputValue);
};
render() {
console.log(this.props);
return (
<div className="Calendar">
<form onSubmit={this.handleSubmit.bind(this)}>
<label>Date/Time</label>
<input type="datetime-local" id="time" step="1" />
<input type="submit" value="Submit" />
</form>
</div>
//{this.render(){return (<UserList />)};
);
}
}
export default graphql(getObjectsQuery, {
options: props => ({
variables: {
timestamp: props.inputvalue
}
})
})(Calendar);
I know it's already solved in another place Reactjs/Graphql: TypeError: Object(...) is not a function
Just to remember (as you stil not learned):
handleSubmit = event => {
event.preventDefault();
console.log(this.state.inputValue); // OLD VALUE
this.setState({
inputValue: new Date(document.getElementById("time").value).valueOf()
});
this.props.data.refetch({
//For some reason
timestamp: this.state.inputvalue
// THERE IS STILL OLD VALUE
// because setState work asynchronously
// IT WILL BE UPDATED LATER
});
console.log(this.state.inputValue); // STILL OLD VALUE
};
To use value from event you could simply use its value, not passing it through 'async buffer' (state).
handleSubmit = event => {
event.preventDefault();
console.log(this.state.inputValue); // OLD VALUE
const timestamp = new Date(document.getElementById("time").value).valueOf()
console.log(timestamp); // NEW VALUE
// use new value directly
this.props.data.refetch({
timestamp: +timestamp
// convert to int
});
// save in state - IF NEEDED at all
this.setState({
inputValue: timestamp
});
};
Of course using setState callback is a quite good workaround, too.
Keep in ming that you can have 2 renders - one when state changes and second when data arrives. If storing value in state isn't really required you can avoid one unnecessary rendering.

React Binding and Populating an Object

I have a React Component which maintains a Local State as shown below:
this.state = {
user : {}
}
I have 2 textboxes on the screen where I can enter name and age. I am sending the values from the textboxes and populating the user object inside the state as shown below:
onTextBoxChange = (e) => {
// this.user is a property on the Component declared inside the // constructor
this.user[e.target.name] = e.target.value
this.setState({
user : this.user
})
}
Is there a better way of populating the state with the user object which consists of name and age.
There is no need to create an extra variable (let user =...) or a member variable (this.user).
Just overwrite previous values using spread syntax.
onTextBoxChange = e => {
this.setState({
user: {
...this.state.user,
[e.target.name]: e.target.value
}
});
};
Here is the fully working version on CodeSandBox.
You can achieve the same by following three different ways:
1) There's no need to creating an this.user property, instead to can achieve the same by using a local variable. So, the function can be changed to:
onTextBoxChange = (e) => {
let user = this.state.user;
user[e.target.name] = e.target.value;
this.setState({
user: this.user
})
}
2) If you're not using user state in input text boxes for value, then you can simply use this.user property instead of using a state, which will cause re-rendering.
You can then use the this.user when the form submitted, for example.
3) Again, If you're not using user state in input text boxes for value, then you can also use React refs and get the value directly from the element when the form is submitted, for example.
You might try this in a parent component:
onTextBoxChange = (field, value) => {
this.setState({user:{
...this.state.user,
[field]: value
}
});
}
and then this in the child component:
onNameChange = (e) => {
this.props.onChange('name', e.target.value)
}
onAgeChange = (e) => {
this.props.onChange('age', e.target.value)
}

Unable to save input picture data in state variable React.js

i'm trying to learn how the image upload process works with react. i have an input that takes image data in and a handler that sets that information to a variable but i am doing something incorrect and not sure what it is.
I want to update picture in state with the picture information and leave the other items in state alone. When i do the below, and console.log after the state of picture stays null.
class Profile extends Component {
constructor() {
super();
this.state = {
userName: "",
userEmail: "",
picture: null
};
this.handleNewImage = this.handleNewImage.bind(this);
}
handleNewImage = event => {
this.setState({
picture: event.target.files[0]
})
console.log(this.state.picture); //gives null still
}
render() {
return (
<input type='file' onChange={this.handleNewImage} />
);
}
}
This probably has nothing to do with images but rather an understanding of setState. React's setState is an async operation so you'd need to console log once the state update is complete:
handleNewImage = event => {
this.setState({
picture: event.target.files[0]
}, () => {
console.log(this.state.picture);
});
}
More info here:
https://reactjs.org/docs/react-component.html#setstate
https://css-tricks.com/understanding-react-setstate/

Resources