Created
February 9, 2017 05:34
-
-
Save mjackson/e1007219bf13fa173ea9a27afadae370 to your computer and use it in GitHub Desktop.
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
/*eslint-disable no-alert */ | |
//////////////////////////////////////////////////////////////////////////////// | |
// Exercise: | |
// | |
// Using context, implement the <Form>, <SubmitButton>, and <TextInput> | |
// components such that: | |
// | |
// - Clicking the <SubmitButton> "submits" the form | |
// - Hitting "Enter" while in a <TextInput> submits the form | |
// - Don't use a <form> element, we're intentionally recreating the | |
// browser's built-in behavior | |
// | |
// Got extra time? | |
// | |
// - Send the values of all the <TextInput>s to the <Form onChange> handler | |
// without using DOM traversal APIs | |
// - Implement a <ResetButton> that resets the <TextInput>s in the form | |
// | |
//////////////////////////////////////////////////////////////////////////////// | |
import React, { PropTypes } from 'react' | |
import ReactDOM from 'react-dom' | |
class Form extends React.Component { | |
static childContextTypes = { | |
form: PropTypes.shape({ | |
submit: PropTypes.func, | |
change: PropTypes.func, | |
reset: PropTypes.func, | |
onReset: PropTypes.func.isRequired | |
}).isRequired | |
} | |
getChildContext() { | |
return { | |
form: { | |
submit: this.props.onSubmit, | |
change: this.props.onChange, | |
onReset: (listener) => { | |
this.listeners.push(listener) | |
}, | |
reset: () => { | |
this.listeners.forEach(listener => listener()) | |
} | |
} | |
} | |
} | |
componentWillMount() { | |
this.listeners = [] | |
} | |
render() { | |
return <div>{this.props.children}</div> | |
} | |
} | |
class SubmitButton extends React.Component { | |
static contextTypes = { | |
form: PropTypes.shape({ | |
submit: PropTypes.func.isRequired | |
}).isRequired | |
} | |
render() { | |
return <button onClick={this.context.form.submit}>{this.props.children}</button> | |
} | |
} | |
class ResetButton extends React.Component { | |
static contextTypes = { | |
form: PropTypes.shape({ | |
reset: PropTypes.func.isRequired | |
}).isRequired | |
} | |
render() { | |
return <button onClick={this.context.form.reset}>{this.props.children}</button> | |
} | |
} | |
class TextInput extends React.Component { | |
static contextTypes = { | |
form: PropTypes.shape({ | |
submit: PropTypes.func, | |
change: PropTypes.func, | |
onReset: PropTypes.func.isRequired | |
}).isRequired | |
} | |
handleKeyDown = (event) => { | |
if (event.key === 'Enter' && this.context.form.submit) | |
this.context.form.submit() | |
} | |
handleChange = (event) => { | |
this.setState({ value: event.target.value }) | |
if (this.context.form.change) | |
this.context.form.change(event) | |
} | |
static defaultProps = { | |
value: '' | |
} | |
state = { | |
value: this.props.defaultValue | |
} | |
handleReset = () => { | |
this.setState({ value: '' }) | |
} | |
componentDidMount() { | |
this.context.form.onReset(this.handleReset) | |
} | |
render() { | |
return ( | |
<input | |
type="text" | |
name={this.props.name} | |
value={this.state.value} | |
placeholder={this.props.placeholder} | |
onKeyDown={this.handleKeyDown} | |
onChange={this.handleChange} | |
/> | |
) | |
} | |
} | |
class App extends React.Component { | |
handleChange = (event) => { | |
console.log(event.target.value) | |
} | |
handleSubmit = () => { | |
alert('YOU WIN!') | |
} | |
render() { | |
return ( | |
<div> | |
<h1>This isn't even my final <code><Form/></code>!</h1> | |
<Form onChange={this.handleChange} onSubmit={this.handleSubmit}> | |
<p> | |
<TextInput name="firstName" placeholder="First Name"/> {' '} | |
<TextInput name="lastName" placeholder="Last Name"/> | |
</p> | |
<p> | |
<SubmitButton>Submit</SubmitButton> | |
<ResetButton>Reset</ResetButton> | |
</p> | |
</Form> | |
</div> | |
) | |
} | |
} | |
ReactDOM.render(<App/>, document.getElementById('app')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment