Last active
May 17, 2020 06:28
-
-
Save casdidier/4739d462c676704279b8d79282cb0224 to your computer and use it in GitHub Desktop.
the fields are not updated after using useEffect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from 'react'; | |
const RoomForm = (initialValues, callback) => { | |
const [inputs, setInputs] = useState(initialValues); | |
const handleSubmit = (event) => { | |
// If we are submitting from a modal, we don't want the RoomSearch page to reload, due to the default submit behaviour. | |
if (event && event.target && event.target.name === 'MODAL_FORM') event.preventDefault(); | |
// Then call back | |
callback(); | |
} | |
const handleInputChange = (event) => { | |
event.persist(); | |
setInputs(inputs => ({ ...inputs, [event.target.name]: event.target.value })); | |
} | |
return { | |
handleSubmit, | |
handleInputChange, | |
inputs | |
}; | |
} | |
export default RoomForm; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect } from 'react'; | |
import { connect } from 'react-redux'; | |
import RoomForm from '../../hooks/RoomHooks'; | |
const RoomUpdate = ({ update, formName, saveButton, roomId, children }) => { | |
const { inputs, handleInputChange, handleSubmit } = RoomForm( | |
{ | |
nombre_de_lits: '', | |
logement: 'Bengalow', | |
lit_simple: '', | |
lit_double: '' | |
}, | |
() => update(inputs) | |
); | |
useEffect(() => { | |
const url = `http://localhost:8000/room/${roomId}`; | |
// Update the document title using the browser API | |
fetch(url, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json' | |
} | |
}) | |
.then((response) => response.json()) | |
.then((jsonResponse) => { | |
return jsonResponse; | |
}) | |
.then((data) => { | |
// console.log('Success:', data); | |
const { nombre_de_lits, logement, lit_simple, lit_double } = data; | |
inputs.nombre_de_lits = nombre_de_lits; | |
inputs.logement = logement; | |
inputs.lit_simple = lit_simple; | |
inputs.lit_double = lit_double; | |
console.log('this is the inputs', inputs); | |
}) | |
.catch((error) => { | |
console.error('Error:', error); | |
}); | |
console.log('mounted'); | |
}); | |
return ( | |
<div className="section is-fullheight"> | |
<h2>ROOM</h2> | |
<div className="container"> | |
<div className="column is-4 is-offset-4"> | |
<div className="box"> | |
<form onSubmit={handleSubmit} autoComplete="off" name={formName}> | |
<div className="field"> | |
<label className="label has-text-centered"> | |
Nombre de couchages | |
</label> | |
<div className="control"> | |
<input | |
className="input" | |
type="number" | |
name="nombre_de_lits" | |
onChange={handleInputChange} | |
value={inputs.nombre_de_lits} | |
required | |
/> | |
</div> | |
</div> | |
<div className="field"> | |
<label className="label has-text-centered"> | |
Type de logement | |
</label> | |
<div className="control"> | |
<input | |
className="input" | |
type="text" | |
name="logement" | |
onChange={handleInputChange} | |
value={inputs.logement} | |
required | |
/> | |
</div> | |
</div> | |
<div className="field"> | |
<label className="label has-text-centered"> | |
Nombre de lits simples | |
</label> | |
<div className="control"> | |
<input | |
className="input" | |
type="number" | |
name="lit_simple" | |
onChange={handleInputChange} | |
value={inputs.lit_simple} | |
required | |
/> | |
</div> | |
</div> | |
<div className="field"> | |
<label className="label has-text-centered"> | |
Nombre de lits double | |
</label> | |
<div className="control"> | |
<input | |
className="input" | |
type="number" | |
name="lit_double" | |
onChange={handleInputChange} | |
value={inputs.lit_double} | |
required | |
/> | |
</div> | |
</div> | |
<button | |
className="button is-block is-fullwidth is-success" | |
type="submit" | |
style={saveButton} | |
> | |
Créer le logement | |
</button> | |
{children} | |
</form> | |
</div> | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
const mapStateToProps = (state, ownProps) => { | |
return {}; | |
}; | |
const mapDispatchToProps = (dispatch, ownProps) => { | |
const url = 'http://localhost:8000/room/update'; | |
return { | |
updateRoom: (inputs) => { | |
const data = { ...inputs }; | |
fetch(url, { | |
method: 'PUT', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify(data) | |
}) | |
.then((response) => response.json()) | |
.then((jsonResponse) => { | |
if (ownProps.displayModal2) ownProps.displayModal2(); | |
return jsonResponse; | |
}) | |
.then((data) => { | |
dispatch({ type: 'UPDATE_ROOM', data }); | |
}) | |
.catch((error) => { | |
console.error('Error:', error); | |
}); | |
} | |
}; | |
}; | |
export default connect(mapStateToProps, mapDispatchToProps)(RoomUpdate); |
- store some default form values in REACT STATE
- useEffect with zero dependencies to request data from API
2.b use setXState to update the state - component rerenders
Okay
First of all, this seems like an awful practise to use a hook outside of a component, especially for something so simple
Even still, you are not updating the state
Did you write this code?
You have not called handleInputChange to reflect a change in the state. Instead, you are updating state directly
best way to do it :
const [formData, setFormData] = useState(RoomForm(/** default values **/));
type FormState = {
username: string,
password: string,
otherThing: number
}
const SomeComponent = () => {
const [formState, setFormState] = useState<FormState>(
username: '',
password: '',
otherThing: 0
);
useEffect(() => getFormStateFromAPI().then(setFormState), []);
return (...);
}
The quick and dirty solution to your problem is to manually call handleInputChange at the end of your useEffect
But like I say, this is bad practise, and you should look up some tutorials to implement something more maintainable
That's fine, and certainly not a bad thing that you tried, but you are externalizing the wrong logic
The logic of performing the API request and modelling the result as an object should be externalized to a class
For example a RoomFormService that performs the API request, uses the axios json method, and collects the fields you need as a type
useEffect(() => {
RoomFormService.getRoom(roomId).then(room => {
setFormState(
nombre_de_lits: room.de_lits
);
});
}, []);
Managing the validation + updating the values is also very simple.
const [formState, setFormState] = useState<FormState>(/* default values */);
return (
<input value={formState.someValue} onChange={newValue => setFormState({...formState, someValue: newValue})} />
);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://discordapp.com/channels/102860784329052160/103696749012467712/711290565844664361