Gian Marco Toso
Drinking coffee and saving the world. Software Engineer and professional geek
A shameless story of self promotion
Gian Marco Toso
@gianmarcotoso
gianmarcotoso
gianmarcotoso.com
polarityb.it
Software Engineer, The Pirate I Was Meant To Be
Born and raised in Turin, Italy
@gianmarcotoso
gianmarcotoso
gianmarcotoso.com
polarityb.it
MSc in Computer EngineeringĀ
Self Employed Software Engineer
Javascript and PHP Developer
Docker
PHP/Laravel
"It was working on my machine!"
The monolith is here to stay
NodeJS/TypeScript
Seriously, it's awesome!
React + Redux
The Flux Capacitor!
import React from 'react'
class MyForm extends React.Component {
state = {
name: '',
password: ''
}
handleFormValueChange =
(ev) => this.setState({[ev.target.name]: ev.target.value})
render() {
return (
<div>
<input
name="name"
onChange={this.handleFormValueChange}
value={this.state.name}
/>
<input
name="password"
onChange={this.handleFormValueChange}
value={this.state.password}
type="password"
/>
</div>
)
}
}
We need to manage the state manually
We actually needĀ a state
Forms cannot be stateless components
The code is almost always the same
š¢
A render prop is a functionĀ that is called by the component it's passed to with some argumentsĀ and returns a valid ReactNode element
Any prop can be a render prop...
... even `children`!
import React from 'react'
class MyContainer extends React.Component {
render() {
return (
<Capitalizer name="billy">
{(capitalizedName) => (
<h1>Hello, {capitalizedName}!</h1>
)}
</Capitalizer>
)
}
}
// Hello, Billy!
The point of using render props is to have components that do some kind of elaboration but leave it to us to decide whatĀ to render with the data they produce
import React from 'react'
class Capitalizer extends React.Component {
render() {
const { name } = this.props
const capitalizedName = name[0].toUpperCase + name.substr(1)
// We are CALLING the children prop!
return this.props.children(capitalizedName)
}
}
In this example, Capitalizer takes a `name` prop and capitalizes the first character. It knows nothingĀ about rendering, because rendering is delegatedĀ to its parent component
Can we use this approach to simplify how we write forms?
Yes!
Ā
(and I made a package that I'll shamelessly promote later...)
We want to be able to write this
import React from 'react'
const MyForm = ({onSubmit}) => (
<FormHandler initial={{name: '', password: ''}}>
{(data, onChange) => (
<div>
<input
name="name"
value={data.name}
onChange={onChange}
/>
<input
name="password"
value={data.password}
onChange={onChange}
/>
<button
type="submit"
onClick={() => onSubmit(data)}
/>
</div>
)}
</FormHandler>
)
FormHandler acts as a minimal state container, updating its internal state every time ourĀ data changes, and passing these changes back to us so that we can render them
import React from 'react'
class FormHandler extends React.Component {
constructor(props) {
super(props)
this.state = {
data: props.initial
}
}
onHandleDataChange =
(ev) => this.setState(state => {
return {
data: {
...state.data,
[ev.target.name]: ev.target.value
}
}
})
render() {
return this.props.children(this.state.data, this.onHandleDataChange)
}
}
I made a package, react-attire, that does this and handles a few other cases, supporting validation and data transformation as well
It also works with React Native ;)
Form Validation with JOI
JSON Form Builder
Thank you! :)
By Gian Marco Toso
Slides for my second talk at the 2017 WebAppConf in Torino
Drinking coffee and saving the world. Software Engineer and professional geek