EN
Is the state updated when I submit a form in React?
1 answers
3 points
I use a <form>
in React and collect input data into a state using useState()
.
How to make sure that the data in the state is up-to-date when the 'submit' button is clicked?
1 answer
4 points
When you use, default events on <input>
elements like onChange
, onInput
or onBlur
to set state, the state is set imidiatelly by handling function. The problem occurs when event occurs in async mode that may be realised by some libraries. It that way, it is good to wait with submit action after all fieds will lose focus or then unlock submit button.
When async mode is used in events you can use some counter to check if all fields lost focus what was show in the second example.
Solutions
Simple React application using embedded <input>
elements:
xxxxxxxxxx
1
// import React, {useState} from 'react';
2
3
const App = () => {
4
const [data, setData] = React.useState({});
5
const handleChange = (e) => {
6
const target = e.target;
7
setData(state => {
8
return {
9
data,
10
[target.name]: target.value
11
};
12
});
13
};
14
const handleSubmit = (e) => {
15
e.preventDefault();
16
console.log(JSON.stringify(data, null, 4));
17
};
18
return (
19
<form onSubmit={handleSubmit}>
20
<label><span>Field 1:</span><input name="field1" defaultValue={data.field1} onInput={handleChange} /></label><br />
21
<label><span>Field 2:</span><input name="field2" defaultValue={data.field2} onChange={handleChange} /></label><br />
22
<label><span>Field 3:</span><input name="field3" defaultValue={data.field3} onBlur={handleChange} /></label><br />
23
{/*
24
Where:
25
onInput calls handleChange function always on when data is input (works similar to onChange)
26
onChange calls handleChange function always on when data is changed (called multiple times during value changing)
27
onBlur calls handleChange function always on when input lost focus
28
*/}
29
<button type="submit">Submit</button>
30
<pre>
31
{JSON.stringify(data, null, 4)}
32
</pre>
33
</form>
34
);
35
};
36
37
const root = document.querySelector('#root');
38
ReactDOM.render(<App />, root );
Source: https://dirask.com/snippets/Dl6lyj
Comples React application using cusomt async <Input>
elements:
xxxxxxxxxx
1
// import React, {useState} from 'react';
2
3
// Component that simluates async and delayed events (not perfect solution but enought for the example).
4
//
5
const Input = ({name, label, value, onInput, onChange, onFocus, onBlur}) => {
6
const state = React.useRef('unfocused');
7
const handleInput = (e) => {
8
setTimeout(() => onInput?.(e), 1000); // delayed because of some reasone
9
};
10
const handleChange = (e) => {
11
setTimeout(() => onChange?.(e), 1000); // delayed because of some reasone
12
};
13
const handleFocus = (e) => {
14
if (state.current === 'unfocused') {
15
state.current = 'focused';
16
onFocus?.(e);
17
}
18
};
19
const handleBlur = (e) => {
20
if (state.current === 'focused') {
21
state.current = 'changing';
22
setTimeout(() => {
23
state.current = 'unfocused';
24
onBlur?.(e);
25
}, 1000); // delayed because of some reasone
26
}
27
};
28
return (
29
<label>
30
<span>{label}</span>
31
<input
32
name={name}
33
defaultValue={value}
34
onInput={handleInput}
35
onChange={handleChange}
36
onFocus={handleFocus}
37
onBlur={handleBlur}
38
/>
39
</label>
40
);
41
};
42
43
const App = () => {
44
const [ready, setReady] = React.useState(3);
45
const [data, setData] = React.useState({});
46
const handleChange = (e) => {
47
const target = e.target;
48
setData(state => {
49
return {
50
data,
51
[target.name]: target.value
52
};
53
});
54
};
55
const handleFocus = (e) => {
56
setReady(state => state - 1);
57
};
58
const handleBlur = (e) => {
59
setReady(state => state + 1);
60
};
61
const handleSubmit = (e) => {
62
e.preventDefault();
63
if (ready === 3) {
64
//TODO: dava validation (e.g. required fields, etc.)
65
//TODO: data sending
66
console.log(JSON.stringify(data, null, 4));
67
} else {
68
//TODO: remember information about submit action and send when all focus lost
69
}
70
};
71
return (
72
<form onSubmit={handleSubmit}>
73
<Input
74
name="field1"
75
label="Field 1"
76
value={data.field1}
77
onFocus={handleFocus}
78
onBlur={handleBlur}
79
onInput={handleChange}
80
/>
81
<br />
82
<Input
83
name="field2"
84
label="Field 2"
85
value={data.field2}
86
onFocus={handleFocus}
87
onBlur={handleBlur}
88
onChange={handleChange}
89
/>
90
<br />
91
<Input
92
name="field3"
93
label="Field 3"
94
value={data.field3}
95
onFocus={handleFocus}
96
onBlur={(e) => {
97
handleChange(e);
98
handleBlur(e);
99
}}
100
/>
101
<br />
102
<div>Ready inputs: {ready}</div>
103
<button type="submit">Submit</button>
104
<pre>
105
Preview: {JSON.stringify(data, null, 4)}
106
</pre>
107
</form>
108
);
109
};
110
111
const root = document.querySelector('#root');
112
ReactDOM.render(<App />, root );
0 commentsShow commentsAdd comment