@lucianomlima
@rodrigopr
Meetup React Salvador #5
import React from 'react';
function Welcome(props) {
return <h1>Hello {props.name}</h1>;
}
function Text(props) {
return <div>{props.text}</div>;
}
function App() {
return (
<React.Fragment>
<Welcome name="Johnny" />
<Text text="Your App is Ready!" />
</React.Fragment>
);
}
import React from 'react';
const Welcome = props => (<h1>Hello {props.name}</h1>);
// const Welcome =({ name }) => (<h1>Hello {name}</h1>);
const Text = props => (<div>{props.text}</div>);
// const Text =({ text }) => (<div>{text}</div>);
const App = () => (
<React.Fragment>
<Welcome name="Johnny" />
<Text text="Your App is ready!" />
</React.Fragment>
);
( with arrow functions )
import React from 'react';
const Welcome =({ name }) => (<h1>Hello {name}</h1>);
const Text =({ text }) => (<div>{text}</div>);
class App extends React.Component {
componentDidMount() {
doSomething();
}
render() {
<React.Fragment>
<Welcome name="Johnny" />
<Text text="Your App is ready!" />
</React.Fragment>
}
}
import React from 'react';
const Avatar = ({ name, image }) => (<img src={image} alt="name" />);
const Welcome = props => (
<div className="Welcome">
<Avatar {...props} />
<h1>Hello {props.name}</h1>
</div>
);
// OR
const UserInfo = props => (
<div className="UserInfo">
<Avatar {...props} />
<div className="UserInfo-name">
<span>{props.name}</span>
</div>
</div>
);
import React from 'react';
import MONTH_NAMES from './somewhere';
class Clock extends React.Component {
state = {
date: new Date()
}
getDate(date) {
const month = MONTH_NAMES[date.getMonth()];
return `${date.getDate()}/${month}/${date.getFullYear()}`;
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.getDate(this.state.date)}.</h2>
</div>
);
}
}
Evitar duplicação de código
Compartilhar comportamentos
Pensar de forma escalável
Pensar no impacto na performance
Pensar na rastreabilidade de bugs
import React from 'react';
class Form extends React.Component {
...
handleSubmitClick = (e) => {
e.preventDefault();
const name = this._name.value;
myCustomSubmit(name);
}
render() {
return (
<form>
<input type="text" ref={input => this._name = input} />
<button onClick={this.handleSubmitClick}>Sign up</button>
</form>
);
}
}
import React from 'react';
class Form extends React.Component {
state = {
name: ''
}
handleNameChange = (event) => {
this.setState({ name: event.target.value });
}
handleSubmitClick = (e) => {
e.preventDefault();
myCustomSubmit(this.state.name);
}
render() {
return (
<form>
<input type="text" value={this.state.name} onChange={this.handleNameChange} />
<button onClick={this.handleSubmitClick}>Sign up</button>
</form>
);
}
}
Mais genéricos, maior reutilização
Componentes pais tem mais liberdade em como lidar com um componente filho
Mais simples, menos código envolvido
Ganha complexidade quando necessita suportar vários casos de uso
class Toggle extends React.Component {
state = {
on: false
}
isControlled(prop) {
return this.props[prop] !== undefined;
}
getState() {
// Need to decide from where to get the value
return {
on: this.isControlled('on') ? this.props.on : this.state.on
};
}
toggle = () => {
if (this.isControlled("on")) {
this.props.onToggle(!this.getState().on);
} else {
// After update state, call onToogle to update parent
this.setState(
({ on }) => ({ on: !on }),
() => {
this.props.onToggle(this.getState().on);
}
);
}
}
render() {
return <Switch on={this.getState().on} onClick={this.toggle} />;
}
}
<MyComponent>Hello world!</MyComponent>
<div>Hello World</div>
<div>
Hello World
</div>
<div>
Hello
World
</div>
<div>
Hello World
</div>
( String Literals )
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
<MyList>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</MyList>
render() {
return [
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
( JSX Children )
<MyComponent>{'foo'}</MyComponent>
const Item = (props) => (<li>{props.message}</li>);
const List = () => {
const items = ['finish doc', 'submit pr', 'code review'];
return (
<ul>
{items.map(message => <Item key={message} message={message} />)}
</ul>
);
}
render() {
return [
<li key="A">`${first} item`</li>,
<li key="B">`${second} item`</li>,
<li key="C">`${third} item`</li>,
];
}
( JavaScript Expressions )
import React from 'react';
// Calls the children callback numTimes to produce a repeated component
const Repeat = (props) => {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i));
}
return <div>{items}</div>;
}
const ListOfTenThings = () => (
<Repeat numTimes={10}>
{(index) => (
<div key={index}>
This is item number {index} in the list
</div>
)}
</Repeat>
);
export default ListOfTenThings;
( Functions as Children )
"Dependency Injection" para componentes
Originado das High Order Functions
Isolamento de lógica para reaproveitamento
Isolamento de lógica para abstração
Isolamento de lógica para código mais limpo
Não usar no render
Propriedades estática não são copiadas
Gera maior acoplamento de código
Pode tornar o debug mais difícil
Ref não é propagado automaticamente
import { connect } from '...';
import { compose, withState, ... } from '...';
const enhancer = compose(
connect(...),
withState(...),
withSomething,
);
const EnhancedComponent = enhancer(Component);
/*
|-- connect render
|-- withState render
|-- withSomething render
|-- Component render
*/
export const Component = (props) => {
return (<div> ... </div>);
};
const enhancer = compose(
...
);
export default enhancer(Component);
import EnhancedComponent, { Component } from '../';
describe('Component', () => {
// unit-test Component directly
});
describe('EnhancedComponent', () => {
// you can also do integration test
});
( talvez só não saiba... )
Relay.createContainer()
Redux: connect()
MobX: observer()
react-loadable
const Example = () => {
return (
<Theme>
{theme => (
<Counter>
{counter => (
<Toggle>
{toggle => (
<div style={{ color: theme === 'light' ? '#000' : '#fff' }}>
<span>{`Count: ${counter}`}</span>
<button onClick={toggle}>{'Toggle'}</button>
</div>
)}
</Toggle>
)}
</Counter>
)}
</Theme>
)
}
const Composed = adopt({
theme: <Theme />,
counter: <Counter />,
toggle: <Toggle />,
})
const Example = () => (
<Composed>
{({ theme, counter, toggle }) => (
<div style={{ color: theme === 'light' ? '#000' : '#fff' }}>
<span>{`Count: ${counter}`}</span>
<button onClick={toggle}>{'Toggle'}</button>
</div>
)}
</Composed>
);
Tradução: Obrigado