Here will be my notes about React
-
-
Save ricardocanelas/de9e7c7d40a046d710f0d629df000f45 to your computer and use it in GitHub Desktop.
FUNDAMENTOS DE REACT
Aula 2 - Renderização da UI com o React
Aula 3 - Gerenciamento de Estados
Aula 4 - Gerenciamento de Estados
Aula 5 - Gerenciando a localização na aplicação com o React Router
A composição ocorre quando funções simples são combinadas para criar outras mais complexas. Pense em cada função como um bloco de construção único que faz uma coisa (DOT - "does one thing")
Imperative significa: expressar um comando; comandar.
Quando um código de JavaScript é escrito de maneira imperativa, dizemos ao JavaScript exatamente o que fazer e como fazer isso.
Com o código declarativo, não codificamos todas as etapas para chegar ao resultado final. Em vez disso, declaramos o que queremos fazer, e o JavaScript se encarregará de fazê-lo.
const people = ['Amanda', 'Geoff', 'Michael', 'Richard', 'Ryan', 'Tyler']
const excitedPeople = people.map(name => name + '!')
"JavaScript", vou dar esse conjunto de nomes e quero que você mapeie-os e coloque uma exclamação em cada um ao final. Depois, devolva-me o resultado, por favor."
O código imperativo instrui o JavaScript sobre como ele deve executar cada etapa. Com o código declarativo, dizemos ao JavaScript o que queremos obter e o deixamos tomar conta das etapas de execução.
O React é declarativo, pois escrevemos o código que queremos, e o React é responsável por pegar o código declarado e executar todas as etapas de JavaScript/DOM para nos fornecer o resultado desejado.
Os dados fluem em uma única direção, do pai para o filho. React usa esse tipo de direcionamento.
Frameworks de front-end, como o Angular e o Ember, utilizam a ligação de dados bidirecionais (two-way data bindings).
const people = ['Rico', 'Canelas', 'Fernanda'];
const lenPeople = people.map(person => person.length);
const shortsPeople = people.filter(person => person.length < 5);
O método .createElement() do React requer uma descrição de um elemento e retorna um objeto JavaScript simples.
O .createElement() retorna um elemento Root
import React from 'react'
const helloElem = React.createElement('div', {'className': 'world'}, 'Hello World!')
const myListElem = React.createElement('ol', null,
React.createElement('li', null, 'Michael'),
React.createElement('li', null, 'Richard'),
React.createElement('li', null, 'Evelly'),
)
const people = ['Michael', 'Richard', 'Evelly']
const peopleListElem = React.createElement('ol', null,
people.map((person, index) => (
React.createElement('li', { key: index }, person),
))
)
Usando o 'react-dom' para renderizar.
import React from 'react'
import ReactDOM from 'react-dom'
const helloElem = React.createElement('div', {'className': 'world'}, 'Hello World!');
ReactDOM.render(helloElem, document.getElementById('root'));
Ao escrever JSX, tenha em mente que ele deve retornar apenas um único elemento.
const people = ['Michael', 'Richard', 'Evelly']
const peopleListElem = (
<ol>
{people.map((person,index) => (
<li key={index}>{person}</li>
))}
</ol>
)
Existe apenas um método absolutamente necessário em qualquer classe de componente de React: o método render().
Essas classes de componentes devem seguir o princípio da responsabilidade única e apenas "fazer uma coisa". Se ele gerencia muitas tarefas diferentes, pode ser uma boa idéia decompor seu componente em subcomponentes menores.
Uma ótima mentalidade para se adquirir ao criar aplicativos em React é pensar em componentes.
import React from 'react'
import ReactDOM from 'react-dom'
class ContactList extend React.Component {
render () {
$greeting = 'Hello World'
return (
<div>
<h1>$greeting</h1>
<p>lorem ipsum...</p>
</div>
)
}
}
ReactDOM.render(
<ContactList>,
document.getElementById('root')
)
O JSX é incrível, mas precisa ser transpilado para JavaScript regular antes de chegar ao navegador. Normalmente, usamos um transpiler como o Babel para fazer isso. Podemos executar o Babel com uma ferramenta de build como o Webpack, que ajuda a agrupar todos nossos assets (arquivos de JavaScript, CSS, imagens, etc.) para projetos na web.
Para simplificar essas configurações iniciais, podemos usar o pacote do aplicativo Create React, do Facebook, para cuidar de toda a configuração para nós!
npm install -g create-react-app
create-react-app contactsApp
Vai instalar: React, React-Dom, React-Scripts
React-Scripts vem com: Babel, Webpack, Webpack-Dev-Server
Conceitos: Props, States, Componentes Funcionais, Componentes Controlados.
Se você deseja que seu componente armazene dados locais mutáveis, considere usar o state para manter essa informação.
Se a mudança de algumas informações ao longo do tempo não é esperada, e geralmente é projetada para ser "somente leitura" em seu aplicativo, considere usar props em vez disso.
Um prop é qualquer entrada que você passa para um componente React. Assim como um atributo HTML, um nome e valor do prop são adicionados ao componente.
Podemos pensar em passar os props para componentes, assim como passamos argumentos para funções. Assim como podemos acessar os argumentos passados para uma função em JavaScript, podemos também acessar os props de um componente com this.props (ou props em componentes funcionais sem estado).
Qualquer prop passado para um componente é acessível com o objeto this.props.
O PropTypes é um pacote que nos permite definir os tipos de dados que queremos ter e nos avisar, durante o desenvolvimento, se o prop que foi passado para o componente coincide ou não com o esperado.
yarn install prop-types
class User extends React.Components {
render() {
return (
<p>Username: {this.props.username}</p>
)
}
}
Componente funcional sem estado.
const User = (props) => {
return (
<p>Username: {props.username}
)
}
Os componentes controlados referem-se a componentes que representam um formulário, mas a "fonte da verdade" para esse estado do formulário vive dentro do estado do componente em vez de dentro do DOM. Os benefícios dos componentes controlados são:
- Validação de entrada instantânea
- Desativação/habilitação de botões de maneira condicional
- Imposição de formatos de entrada
class NameForm extends React.Component {
state = { email: '' }
handleChange = (event) => {
this.setState({email: event.target.value });
}
render () {
return (
<form>
<input type='text' value={this.state.email} onChange={this.handleChange} />
</form>
)
}
}
O render() só é usado para exibir conteúdo, apenas!
Códigos que devem lidar com requisições Ajax, requisição HTTP, recuperar dados devem estar no ciclo de vida (lifecycle events)
componentWillMount() - invocado imediatamente antes do componente ser inserido no DOM
componentDidMount() - invocado imediatamente depois do componente ser inserido no DOM
componentWillUnmount() - invocado imediatamente antes do componente ser removido do DOM
componentWillReceiveProps() - invocado sempre que o componente está prestes a receber novas props
Em qual método do ciclo de vida você deveria realizar requisições Ajax ou de APIs? RE: componentDidMount
Cada um é executado em um momento diferente, mas podemos separá-los em três categorias:
- constructor()
- componentWillMount()
- render()
- componentDidMount()
- componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
- componentWillUnmount()
SPA, single-page applicatiions - Aplicações de página única.
O React Router transforma projetos React em aplicações single-page
npm install --save react-router-dom
Vai ouvir as mudanças no URL, quando as mudanças acontecerem, ele faz a tela certa aparecer.
Você precisa envolver todo o seu aplicativo em um componente BrowserRouter:
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render(
<BrowserRouter><App /><BrowserRouter>,
document.getElementById('root')
)
<Link to={{
pathname: '/courses',
search: '?sort=name',
hash: '#the-hash',
state: { fromDashboard: true }
}}>
Courses
</Link>
é o componente que decidirá quais components serão renderizados com base em cada caminho de URL. Route pega um caminho que corresponde ao URL, então o Route vai renderizar uma IU.
<Route exact path='/' render={() => (
<ListContact
contact={this.state.contacts}
/>
)}/>
<Route path='/create' component={CreateContact} />
REACT E REDUX
Aula 2 - Redux na sua essência
Aula 4 - Arquitetando uma Redux Store
Aula 5 - Middleware para Redux
As funções puras se prestam a um código de melhor qualidade, e ter isso em mente ao construir os aplicativos fará de você um programador mais capaz.
Tres items que deve ser:
- Return one and the same result if the same arguments are passed in
- Depend solely on the arguments passed into them
- Do not produce side effects
const square = (x) => x * x
Veja mais em: https://www.gitbook.com/book/drboolean/mostly-adequate-guide-old/details
// Inpura
const tipPercentage = 0.15
const calculateTip = (cost) => cost * tipPercentage
// Pura
const calculateTip = (cost, tipPercentage = 0.15) => cost * tipPercentage
Enfatiza funções puras..
Enfatiza funções impuras..
Pega uma função (ou seja, um callback) como argumento.
Exemplo de funções HO: reduce, map, filter
A ideia central de .reduce() é que ela pega uma grande quantidade de dados, mas retorna um único valor.
const iceCreamStats = [
{ name: 'Amanda', gallonsEaten: 3.8},
{ name: 'Richard', gallonsEaten: 5.2}
]
iceCreamStats.reduce((accumulator, currentValue) => {
return accumulator + currentValue.gallonsEaten
}, 0)
// return: 9
- Action
- Reducers
- The Store
- Action são enviadas pela store
- Para criar a store, precisamos do reducer.
- O reducer usa as actions.
Um fluxo de dados unidirecional
Resumo: os principais conceitos do Redux são as actions, os reducers e a store. A store é o single source of truth sobre o estado de seu aplicativo, os reducers atualizam e especificam o formato da store, e as actions são pacotes de informação que dizem aos reducers que tipos de eventos aconteceram no aplicativo.
Actions são objetos JavaScript que descrevem qualquer evento que deva atualizar o estado do aplicativo.
Esses objetos devem ter uma propriedade type para distinguir o tipo específico de action que ocorreu.
Recomendações: Faça com que seus recursos enviem apenas os dados necessários! É importante manter actions o mais concentradas possíveis, sem efeitos colaterais.
{
type: 'DELETE_COMMENT',
id: 3
}
deleteComment = id => ({
type: 'DELETE_COMMENT',
id: id
})
const CREATE_MEAL = 'CREATE_MEAL'
const mealCreator = (id) => ({
type: CREATE_MEAL,
id
})
console.log(mealCreator(1))
// { type: 'CREATE_MEAL', id: 1 }
Um reducer é, simplesmente, uma função à qual são passados esses dois argumentos.
Um reducer recebe o estado atual e uma action que foi despachada e, então, decide como transformar o estado atual em um estado novo, baseado na action que recebeu.
Regras:
- Reducer deve ser uma função pura.
- Reducer deve receber o estado atual e uma action, e retornar o novo estado
- Reducer não deve produzir efeitos colaterais (solicitações assíncronas, alteração de variáveis de escopo, etc.)
function reducer (state = initialState, action) {
const newState = {...state}
return newState // always return a state
}
function reducer (state = initialState, action) {
switch (action.type) {
case 'SUBMIT_USER' :
return Object.assign({}, state, {
user: action.user
})
}
}
O que comanda a parada toda
const immaStore = Redux.createStore(<reducer>)
immaStore.getState()
immaStore.dispatch(<action object>)
immaStore.subscrive(<listener function>)
https://www.youtube.com/watch?v=AlFCMlK5cpU
A maior vantagem do react-redux é percebida no despacho de actions e no acesso à store do Redux a partir dos seus componentes React
- Provider
- Connect
import { Provider } from 'react-redux';
const store = createStore(myReducer)
<Provider store={store}>
<App />
</Provider>
O Provider permite que o Redux passe dados da store para quaisquer componentes React que precisem. Ele usa a funcionalidade de contexto do React para fazer isso funcionar.
Também pode ser chamado de 'partial application'
function greet(name, message) {
return `${message}, ${name}!`;
}
Digamos que, por qualquer motivo, gostaríamos de esperar para message mais tarde. Uma forma de conseguir fazer isso seria retornar uma função que aceita uma mensagem, que pudesse ser chamada mais tarde.
// the curried function
const greet = (name) {
return (message) => {
return `${message}, ${name}!`;
}
}
greet('Ricardo')('Yo yo')
Currying é o processo de fornecer entradas parcialmente a uma função que precisa de informações adicionais. A parte da API do Redux que usa currying é seu método connect(). Vamos dar uma olhada!..
connect() é uma função que permite que um componente obtenha dados e despache actions a partir de uma store do Redux. Sua assinatura é interessante. Usando todos os argumentos, ela fica assim:
connect(mapStateToProps, mapDispatchToProps)(MyComponent)
mapStateToProps() permite que você especifique que dados do store você quer que sejam passados para seus componente React.
Ele pega do state de store, um argumento opcional ownprops, e retorna um objeto. Veja sua assinatura completa:
mapStateToProps(state, [ownProps])
const mapStateToProps = (state, ownProps) => ({
name: state.user.name,
age: state.user.age
});
const mapStateToProps = (state, ownProps) => ({
photos: state.photos.filter(photo => photo.user === ownProps.user)
});
Quando você conecta um componente, aquele componente será passado automaticamente para o método dispatch() do Redux
const mapDispatchToProps = dispatch => ({
boundUpdateName: (name) => dispatch(updateName(name))
});
combineReducers() é uma função auxiliar fornecida pelo Redux que transforma um objeto cujos valores são diferentes funções reducer em uma única função reducer.
Passamos então este “root reducer” para o createStore() para criar a store do aplicativo.
// in: reducers/root_reducer.js
import { combineReducers } from 'redux';
function users (state = {}, action) { ...}
function books (state = {}, action) { ... }
export default combineReducers({
users,
books,
});
// in: store/store.js
import rootReducer from '../reducers/root_reducer';
const store = createStore(rootReducer)
Normalização é o processo de remover porções de dados duplicadas e garantir que os dados estejam estruturados da maneira menos profunda possível.
const people = {
personA: 'myInfoA',
personB: 'myInfoB',
personC: 'myInfoC',
}
const friends = ['personA', 'personB']
getFriendInformation = friends.map((friend) => people[friend])
Coloque em mente: não duplique seus dados e mantenha sua store o menos profundo possível.
Middleware.. um ponto de extensão criado por terceiros entre o despacho de uma action e o momento em que ela chega ao reducer.
Uma vez que o middleware recebe a action, ele pode, então, realizar uma série de operações, incluindo:
- Produzir um efeito colateral (ex: fazer um log do estado)
- Processar a action por si só (ex: fazendo uma requisição HTTP assíncrona)
- Redirecionando a action (ex: para outro middleware)
- Executar algum código durante o despacho
- Despachar actions suplementares
...e tudo isso é feito antes da action ser encaminhada para o reducer!
Doc: https://redux.js.org/advanced/middleware
Redux nos fornece a função applyMiddleware(), que podemos usar como nosso argumento enhancer.
store.createStore(reducer, [preloadedState], [enhancer])
applyMiddleware() aceita múltiplos argumentos, então, caso necessário, podemos aplicar mais de um middleware a um aplicativo.
const logger = store => next => action => {
console.group(action.type)
console.info('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
console.groupEnd(action.type)
return result
}
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store = createStore(
reducer,
composeEnhancers(
applyMiddleware(logger)
)
)
Middlewares:
- https://github.com/evgenyrodionov/redux-logger
- https://github.com/gaearon/redux-thunk
- https://github.com/xgrommx/awesome-redux#react---a-javascript-library-for-building-user-interfaces
- ...
// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers/root_reducer';
const store = () => createStore(rootReducer, applyMiddleware(thunk));
export default store;
Nos permite escrever action creators assíncronos que retornam funções em vez de objetos, nosso novo action creator, agora, pode ser assim:
// util/todos_api_util.js
export const fetchTodos = () => fetch('/api/todos');
import * as TodoAPIUtil from '../util/todo_api_util';
export const RECEIVE_TODOS = "RECEIVE_TODOS";
export const receiveTodos = todos => ({
type: RECEIVE_TODOS,
todos
});
export const fetchTodos = () => dispatch => (
TodoAPIUtil
.fetchTodos()
.then(todos => dispatch(receiveTodos(todos)))
);
O thunk pode, então, ser usado para atrasar o despacho de uma action ou para despachar somente se uma certa condição for satisfeita (ex: um pedido é resolvido).
Veja mais em:
- http://redux.js.org/docs/advanced/AsyncFlow.html
- http://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout/35415559#35415559
Não existe um “jeito certo” de dividir as coisas, embora haja convenções que podemos praticar para ajudar a gerenciar a complexidade do Redux.
Exemplos de mundo real:
...fique à vontade para escolher a estrutura que fizer mais sentido para você.
REACT NATIVE
- iOS usa o Xcode
- Android usa o Android Studio
- Expo: iOS and Android
Usaremos o Create React Native App
para desenvolver para iOS e para Android. Vantagens: Setup simple e rápido; sem necessidade do Xcode ou Android Studio. Desvantangens: com projetos já existentes; modulos nativos para cada sistema.
Usaremos o Expo
que é um conjunto de ferramentas e serviços que nos permitem construir aplicativos nativos (iOS e Android) com Javascript. O Expo facilita a construçao de aplicativos móveis sem precisar escrever código nativo (por exemplo: Swhift, Objetive C, Java)
O Expo, junto ao Create React Native App, é a maneira mais rápida de começar.
Mas se quise Construindo Projetos com Código Nativo, clique no link.
npm install -g create-react-native-app
ou yarn global add create-react-native-app
Vamos seguir o tutorial da documentação
SETUP:
- Install Node.js
- Install Pyhton2
- Install JSDK 8uXXX (JDK 8 is the new Java 10 and 11)
- Install Android Studio
- Install React-Native-CLI
npm install -g react-native-cli
Quando estiver instalando, lembra-se do local de onde é instalado (Adroid SDK Installation Localtion), provavelmente em C:\Users\MyUser\AppData\Local\Android\sdk
Na primeira instalação, quando abrir o Android Studio, vai aparecer alguns alertas (na aba 'messages') para instalar pacotes ou ferramentas adicionais, faça isso. Exemplos: android-23; build tools revision 23;
Proxima coisa é criar um emulator, vá em: Tools/Android/AVD Manager. Create Virtual Device..
/ Nexus5 4.95 / Marshmallow API Level 23 (porque temos o android-23 e build tools) / Finish.
Precisamos adicionar 'Environment Variables'
- JAVA_HOME: C:\Program Files\Java\jdk1.8.0_101
- Path: C:\Users\MyUser\AppData\Local\Android\sdk\platform-tools