Adam Terlson
Software Engineer
github: @adamterlson
twitter: @adamterlson
adam.terlson@gmail.com
Munich, Germany
Display the user's profile image
When the button is pressed, send the message.
Draft the message, when <Enter> is pressed, send.
suite of app-agnostic, semantic components
like making your own version of Bootstrap
WARNING:
This presentation may trigger seizures for developers with sensitivity to rapidly flashing code.
Viewer discretion is advised.
import React from 'react'
import {
TextInput as RNTextInput
} from 'react-native'
const TextInput = ({ value, onChange }) => (
<RNTextInput
value={value}
onChange={onChange}
/>
)
export default TextInput
import React from 'react'
import {
TextInput as RNTextInput
} from 'react-native'
const TextInput = ({ placeholder, value, onChange }) => (
<RNTextInput
placeholder={placeholder}
value={value}
onChange={onChange}
style={{
borderWidth: 1,
borderColor: 'black',
}}
/>
)
export default TextInput
<TextInput>
=
+
+
import React from 'react'
import {
TextInput as RNTextInput
} from 'react-native'
const TextInput = ({ placeholder, value, onChange }) => (
<RNTextInput
placeholder={placeholder}
value={value}
onChange={onChange}
style={{
borderWidth: 1,
borderColor: 'black',
}}
/>
)
export default TextInput
<TextInput>
import React from 'react';
export default WrappedComponent => {
const HOC = props => (
<WrappedComponent {...props} />
);
return HOC;
}
import React from 'react';
import store from '../store'; // redux api
const noop = x => x
export default (
stateProps = noop,
dispatchProps = noop
) => WrappedComponent => props => (
<WrappedComponent
{...props}
{...stateProps(store.getState())}
{...dispatchProps(store.dispatch)}
/>
);
connect()
import React from 'react';
import store from '../store'; // redux api
const noop = x => x
export default (
stateProps = noop,
dispatchProps = noop
) => WrappedComponent => {
class ConnectHOC extends React.PureComponent {
constructor(props) {
super(props);
this.state = store.getState();
}
componentDidMount() {
this.unsubscribe = store.subscribe(
() => this.setState(store.getState())
);
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return (
<WrappedComponent
{...props}
{...stateProps(this.state)}
{...dispatchProps(store.dispatch)}
/>
);
}
}
return ConnectHOC;
);
import React from 'react'
export default register => Component => props => {
const listeners = []
const listenTo = (key, handler) =>
listeners.push(e => {
if (e.key === key) {
handler(e.target.value)
}
})
// Note that props are passed back
register(listenTo, props)
return (
<Component
onKeyDown={e => listeners.forEach(cb => cb(e))}
{...props}
/>
)
}
keyboardEvents()
import TextInput from './TextInput'
import connect from './connect'
export default connect(
null,
dispatch => ({
onSend: (message) => dispatch({
type: 'SEND',
payload: message,
})
})
)(TextInput)
import TextInput from './TextInput'
import connect from './connect'
import keyboardEvents from './keyboardEvents'
export default connect(
null,
dispatch => ({
onSend: (message) => dispatch({
type: 'SEND',
payload: message,
})
})
)(keyboardEvents(
(listenTo, { onSave }) =>
listenTo('Enter', onSend)
)(TextInput))
import TextInput from './TextInput'
import connect from './connect'
import keyboardEvents from './keyboardEvents'
import { flowRight as compose } from 'lodash'
export default compose( // <--- :D
connect(
null,
dispatch => ({
onSend: message => dispatch({
type: 'SEND',
payload: message,
})
})
)
keyboardEvents(
(listenTo, { onSend }) =>
listenTo('Enter', onSend)
)
)(TextInput)
<TextInputSendMessage>>
=
+
// Takes no props!
const SendMessage = () => (
<Container>
<CircularImageUser size={150} />
<TextInputMessage
placeholder="Message..."
/>
<ButtonSend>
<Icon type="mail" />
Send Message!
</ButtonSend>
</Container>
);
SendMessage
<SendMessage>
import React from 'react';
export default (props) => (
props.children(props)
);
ChildrenAsFunction
import connect from './connect'
import ChildrenAsFunction from './ChildrenAsFunction'
export default connect(
({ currentUser }) => ({
name: currentUser.name,
photoUrl: currentUser.userPhotoURL,
})
)(ChildrenAsFunction)
CAFUser
const SendMessage = () => (
<CAFUser>
{({ name, photoUrl }) => (
<Container>
<CircularImage // Delete CircularImageUser
source={photoUrl}
size={150}
/>
<TextInputMessage
placeholder={`Message ${name}...`}
/>
<ButtonSend>
<Icon type="mail" />
Send Message to {name}!
</ButtonSend>
</Container>
)}
</CAFUser>
);
twitter: @adamterlson
github: @adamterlson
adam.terlson@gmail.com
TodoMVC implementation: github.com/adamterlson/todomvc-functional-react
feedback welcome!
For comparison:
github.com/tastejs/todomvc
By Adam Terlson
A demonstration of the power of thinking functionally in react by way of example