React - Formulier gegevens versturen
state
. Dat hebben we gezien in React - State. Maar wat als we nieuwe gegevens willen toevoegen aan de state
? In een echte toepassing zal je eerder met een lege state
beginnen en er items aan toe willen voegen, zoals een takenlijst of een winkelwagentje.Een nieuwe react app maken
- Zorg ervoor dat je openstaande Node.js servers afsluit met Ctrl-C.
- Vooraleer de create-react-app op te starten ga je naar de map waarin je het project wil maken. We gaan op Cloud9 een project maken met de naam react-submit-form. En dat project plaatsen we in de root van onze workspace. Zorg er dus voor dat je in de root staat:
jefinghelbrecht:~/workspace $
In plaats van JefInghelbrecht zie je natuurlijk de naam van je eigen workspace. - Om een create-react-app te maken, voer je de volgende instructie in je terminal uit (zorg ervoor dat je de laatste versie van Node hebt geïnstalleerd, zie Een React App maken):
npx create-react-app react-submit-form
Meer info over npx: Introducing npx: an npm package runner - Als de installatie goed verlopen is, ga dan naar de nieuw aangemaakte map en start het project:
cd react-submit-form
npm start - We maken onze eigen standaardtekst en kieperen de voorgeprogrammeerde code overboord. We behouden alleen:
- index.js
- index.css
- We deleten alle overige bestanden in de /src.
- In index.css plakken we de Primitive CSS van Tania Rascia. Je kan dat vervangen door je eigen CSS of door Bootstrap of om het even welk ander CSS framework.
-
Verwijder de verwijzingen naar
serviceWorker
in index.js. Delete de gemarkeerde lijnen:import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App />, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
Data via een form versturen
- We hebben net App.js verwijderd. Maak een nieuw App.cs bestand in de /src map.
- Vermits we met een lege lijst beginnen en die zullen vullen met de gegevens, die de gebruiker met behulp van een
form
element verstuurt, voorzien we instate
een lege array om de ingegeven albums in op te slaan:import React, { Component } from 'react'; class App extends Component { state = { albums: [] } }
-
We maken nu een formuliercomponent in een nieuw bestand met de naam Form.js in de /src map. We gaan een klassecomponent maken en binnenin zullen we een
constructor()
gebruiken, wat we tot nu toe nog niet hebben gedaan. We hebben deconstructor()
nodig omthis
te kunnen gebruiken en om deprops
van de ouder-component te kunnen benaderen.We gaan de beginstatus van het formulier instellen als een object met enkele lege eigenschappen en die initiële status toewijzen aan
this.state
:import React, { Component } from 'react'; class Form extends Component { constructor(props) { super(props); this.initialState = { nummer: '', titel: '', kaft: '', prijs: '' }; this.state = this.initialState; } }
-
Met ons formulier willen we de
state
van het formulier bijwerken elke keer dat een veld in deform
wordt gewijzigd, en wanneer we op de submit knop drukken zullen al de ingevoerde gegevens worden doorgegeven aan de App state, die de tabel vervolgens zal updaten.Eerst maken we de functie die wordt uitgevoerd als er een
input
element op deform
wordt gewijzigd. Het evenement wordt doorgegeven en we zullen destate
van formulier updaten om hetname
attribuut (sleutel) en hetvalue
attribuut van het gewijzigde HTML invoerelement in destate
op te slaan:handleChange = event => { const { name, value } = event.target; this.setState({ [name]: value }); }
-
We gaan dit eerst laten werken vooraleer verder te gaan met het verzenden van het formulier. In de
render
methode halen we vier eigenschappen uit destate
en wijzen die toe als de waarden van de elementen met eenname
attribuut die overeenkomen met de sleutel uit destate
. We voeren dehandleChange
methode uit wanneer deonChange
event van de input velden wordt afgevuurd. Ten slotte exporteren we de formuliercomponent:render() { const { nummer, titel, kaft, prijs } = this.state; return ( <form> <label>Nummer</label> <input type="text" name="nummer" value={nummer} onChange={this.handleChange} /> <label>Titel</label> <input type="text" name="titel" value={titel} onChange={this.handleChange}/> <label>Kaft</label> <input type="text" name="kaft" value={kaft} onChange={this.handleChange}/> <label>Prijs</label> <input type="text" name="prijs" value={prijs} onChange={this.handleChange}/> </form> ); }
-
Voeg de Table component toe die we in React - State gemaakt hebben (src/Table.js):
import React, { Component } from 'react'; const TableBody = props => { const rows = props.albumData.map((row, index) => { return ( <tr key={index}> <td>{row.nummer}</td> <td>{row.titel}</td> <td>{row.kaft}</td> <td>{row.prijs}</td> <td><button onClick={() => props.removeAlbum(index)}>Delete</button></td> </tr> ); }); return <tbody>{rows}</tbody>; } class Table extends Component { render() { const {albumData, removeAlbum} = this.props; return ( <table> <TableBody albumData={albumData} removeAlbum = {removeAlbum} /> </table> ); } } export default Table;
- In App.cs geven we de Table met daaronder de Form component weer:
import React, { Component } from 'react'; import Table from './Table'; import Form from './Form'; class App extends Component { state = { albums: [] }; render() { // const { albums } = this.state; return ( <div className="container"> <Table albumData={this.state.albums} removeAlbum={this.removeAlbum} /> <Form /> </div> ) }; } export default App;
- Als we naar de front-end van onze app gaan zien we een formulier zonder
submit
knop. Maar omdat we een methode hebben toegewezen aan deonchange
event van deinput
html elementen, kunnen we in de debugger zien dat wanneer we deinput
elementen updaten, dat de lokalestate
van deform
geüpdated wordt:React Submitting Form Data with no submit button - Nu moeten we het mogelijk maken om de gegevens, die in de
form
worden ingetypt, te verzenden en aan deApp state
toe te voegen. Daarvoor maken we een methode met de naamhandleSubmit
in deApp
component die destate
zal bijwerken. Deze methode voegt het nieuwealbum
, die als parameter wordt meegegeven, toe aan de bestaandethis.state.albums
array met behulp van de ES6 spread operator:handleSubmit = album => { this.setState({albums: [...this.state.albums, album]}); }
- We geven deze methode mee als parameter in de
Form
component:<Form handleSubmit={this.handleSubmit} />
- Vervolgens maken we een methode met de naam
submitForm
in deForm
component die de eventhandelaar oproept en dealbum
parameter, die we net gedefiniëerd hebben, aan deForm
state doorgeeft. Deze methode zal ook initiëlestate
opnieuw instellen om deForm
leeg te maken na de submit:submitForm = () => { this.props.handleSubmit(this.state); this.setState(this.initialState); }
- Tenslotte voegen we een submit knop toe aan de
form
. We gebruiken deonClick
event i.p.v. deonSubmit
vermits we niet de standaard submit functionaliteit van deform
gebruiken. DeonClick
event wordt afgehandeld door desubmitForm
methode:<input type="button" value="Submit" onClick={this.submitForm} />
- Als we App uitvoeren kunnen we albums toevoegen en deleten. De
Table
component enTableBody
kunnen data uit destate
halen en dus worden de gegevens van album correct weergegeven:React Submitting Form Data with submit button - Om deze oefening af te ronden voegen we nog enkele eenvoudige componenten toe, namelijk de
thead
entfoot
van de tabel en eencaption
.- We beginnen met een component waarin de headings staan van zowel van het
thead
entfoot
element. In deTable
component in het Table.js bestand voegen we de volgende component toe:const TableHeadings = () => { return ( <tr> <th scope="col">Nummer</th> <th scope="col">Titel</th> <th scope="col">Kaft</th> <th scope="col">€</th> </tr> ); }
- We gebruiken die component als onderdeel van de
TableHeader
component:const TableHeader = () => { return ( <thead> <TableHeadings /> </thead> ); }
- We doen het zelfde voor de
TableFooter
component:const TableFooter = () => { return ( <tfoot> <TableHeadings /> </tfoot> ); }
- En een component voor de caption:
const TableCaption = () => { return ( <caption> Jommeke strips </caption> ); }
- Tenslotte voegen die eenvoudige componenten toe aan de
Table
component:class Table extends Component { render() { const {albumData, removeAlbum} = this.props; return ( <table> <TableCaption /> <TableHeader /> <TableBody albumData={albumData} removeAlbum = {removeAlbum} /> <TableFooter /> </table> ); } }
- En dit is het resultaat:
React Submitting Form Data with Simple Components
- We beginnen met een component waarin de headings staan van zowel van het
- Let erop dat we niet de standaard submit functionaliteit van het
form
element hebben gebruikt.