Skip to content

Instantly share code, notes, and snippets.

@octaviogb
Created April 29, 2016 04:07
Show Gist options
  • Save octaviogb/b6977aa44e059d7768a6fbaa018add5d to your computer and use it in GitHub Desktop.
Save octaviogb/b6977aa44e059d7768a6fbaa018add5d to your computer and use it in GitHub Desktop.
Android React Native exemplo comentado
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