Created
April 29, 2016 04:07
-
-
Save octaviogb/b6977aa44e059d7768a6fbaa018add5d to your computer and use it in GitHub Desktop.
Android React Native exemplo comentado
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
import React, { | |
AppRegistry, // Registrador de aplicativo | |
StyleSheet, // Gerador de folha de estilos | |
Text, // Enclosure de textos | |
TextInput, // Input de textos | |
Image, // Objeto de imagem | |
TouchableNativeFeedback,// Objeto clicável para Android | |
View, // Caixa genérica, tipo div | |
Component, // Componente do React Native | |
PropTypes // Propriedades | |
} from 'react-native'; | |
function getData(username){ | |
// Utiliza o fetch api (https://developer.mozilla.org/en/docs/Web/API/Fetch_API) | |
// para fazer a consulta na API aberta do github | |
return fetch(`https://api.github.com/users/${username}`) | |
.then((d) => d.json()); // Pega a resposta e converte para json | |
} | |
class Input extends Component { | |
// Definição das propriedades dos componentes | |
// isso é importante pois serve tanto como validação | |
// quanto inicialização com valor vazio | |
static propTypes = { | |
onChange: PropTypes.func, | |
value: PropTypes.string, | |
label: PropTypes.string.isRequired // vê? é requerido... | |
}; | |
render() { | |
const {onChange, onSubmit, value, label} = this.props; // Gosto de fazer essa separação para não ter que escrever | |
// muita 'dot notation' no JSX | |
return (<View style={{position: 'relative'}}> | |
<Text>{label}</Text> | |
<TextInput onSubmitEditing={onSubmit} onSubmitBlur={true} style={styles.input} onChangeText={(ev) => onChange && onChange(ev)} value={value||''}/> | |
</View>); | |
} | |
} | |
// A melhor prática seria colocar cada componente | |
// em um arquivo separado, na pasta de componentes | |
class Button extends Component { | |
static propTypes = { | |
label: PropTypes.string.isRequired, | |
onPress: PropTypes.func | |
}; | |
render() { | |
const {label, onPress} = this.props; | |
return (<TouchableNativeFeedback onPress={(ev)=> onPress && onPress(ev)} | |
background={TouchableNativeFeedback.Ripple('white')}> | |
<View style={styles.button}> | |
<Text style={styles.buttonText}> | |
{label} | |
</Text> | |
</View> | |
</TouchableNativeFeedback>); | |
} | |
} | |
class Card extends Component { | |
static propTypes: { | |
data: PropTypes.object | |
}; | |
render() { | |
const {name, location, email, avatar_url} = this.props.data; | |
return (<View style={styles.card}> | |
<Image | |
style={styles.avatar} | |
source={{uri: avatar_url}} | |
/> | |
<Text>Nome:</Text> | |
<Text>{name}</Text> | |
<Text>Localiação:</Text> | |
<Text>{location}</Text> | |
<Text>Email:</Text> | |
<Text>{email}</Text> | |
</View>); | |
} | |
} | |
// Esse seria o componente importado | |
// toranando a aplicação genérica | |
class SampleApp extends Component{ | |
constructor(props) { | |
super(props); // Compece sempre com o 'super(props)' | |
this.state = { | |
isFetching: false, // Isso é bacana para colocar um spinner | |
error: null, // Como não temos muito tempo, não tratarei erros | |
data: null, // Aqui serão definidos os valores do retorno da API | |
username: null, // Este é o nome de usuário que será consultado | |
} | |
} | |
onChange(text) { | |
console.log('change', text); | |
this.setState({ | |
...this.state, | |
username: text.toLowerCase() | |
}); | |
} | |
send() { | |
if(!this.state.username) { | |
alert('Nome de usuário inválido'); // É possível lançar um alerta como no browser | |
return false; | |
} | |
console.log('send'); | |
this.setState({ | |
...this.state, | |
isFetching: true, | |
error: null, | |
}); | |
getData(this.state.username) | |
.then((d) => this.setState({ | |
...this.state, | |
data: d, | |
isFetching: false | |
}, () => console.log('success', this.state.data))) | |
.catch((err) => this.setState({ | |
...this.state, | |
error: err, | |
isFetching: false | |
}, () => console.log('error', this.state.error))) | |
} | |
render() { | |
return (<View style={styles.container}> | |
<Input label="Usuário" onSubmit={this.send.bind(this)} onChange={this.onChange.bind(this)} value={this.state.username}/> | |
<Button label="Buscar" onPress={this.send.bind(this)}/> | |
{this.state.data && <Card data={this.state.data}/>} | |
</View>); | |
} | |
} | |
// A folha de estilos do react-native parece CSS, mas não é! | |
var styles = StyleSheet.create({ | |
container: { | |
flex: 1, // Todo o layout do react-native é em flexbox | |
justifyContent: 'space-between', | |
padding: 5, // Não é necessário colocar 'px' | |
paddingTop: 20, | |
backgroundColor: '#F5FCFF' // Não há shorthands, muitas propriedades acabam um pouco diferentes do CSS | |
}, | |
input: { | |
flex: 1, // Esta é a proporção que o objeto irá tomar no container | |
height: 40 | |
}, | |
// hr: (No Android não precisamos disso) | |
button: { | |
alignSelf: 'center', | |
margin: 5, | |
height: 40, | |
width: 200, | |
padding: 10, | |
backgroundColor: 'purple', | |
borderRadius: 5, | |
elevation: 2 // Isso dá sombra, mas só funciona após o Lollipop | |
}, | |
buttonText: { | |
textAlign: 'center', // Alinhamento e estilos de texto só podem ser aplicados em <Text/> | |
color: 'white' | |
}, | |
card: { | |
flex: 2, // Este objeto poderá ser o dobro dos outros | |
backgroundColor: '#fefefe', | |
margin: 10, | |
padding: 5, | |
elevation: 3 | |
}, | |
avatar: { | |
width: 120, | |
height: 120, | |
borderRadius: 60, // para arredondar 100%, use metade do width e height aqui | |
alignSelf: 'center', | |
borderWidth: 1, | |
margin: 15 | |
} | |
}); | |
AppRegistry.registerComponent('SampleApp', () => SampleApp); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment