React Native - Como eu posso fazer isso com redux?

21/06/2019

0

Estou começando agora com React native, e agora me deparei com a seguinte situação.. primeiramente o projeto que estou usando já vem com algumas coisas prontas, então já foi criada a store, tem algumas coisas usando o redux no app já, e eu fiz a seguinte tela para estudar:

import React, { Component } from 'react';
import { View, Text, TextInput, StyleSheet} from 'react-native';
import { Actions } from 'react-native-router-flux';
import { MyButton } from '../../components';

//import { mudaTexto } from '../../actions';
//import { connect } from 'react-redux';


class Screen1 extends Component {

    constructor(props){
        super(props)
        this.state ={resultadoText:"", texto:"" }
        this.mudaTexto = this.mudaTexto.bind(this)
      }

      //Action
      mudaTexto(){
          let textoU = this.state.texto
          let s = this.state
          s.resultadoText = textoU
          this.setState(s)
    }

    render(){
        return(
                <View  style={[styles.view, {flex:1}]}>
                    <Text style={[styles.txt, {marginTop:0}]}>Essa é a tela 1</Text>
                    <TextInput placeholder='Escreva aqui seu texto'
                    style={[styles.txt, {fontSize:25}]}
                    onChangeText={(texto) => {this.setState()}}>
                    </TextInput>
                    <MyButton onPress={this.mudaTexto} text='Enviar texto'/>
                    <Text
                    style={[styles.txt]}>{this.state.resultadoText}
                    </Text>
                    <View style={styles.view} >
                    <MyButton onPress={()=>Actions.home()} text='Voltar' />
                    </View>
                </View>          
        )
    }
}
const styles = StyleSheet.create({
    txt: {
        fontSize:40,
        textAlign:'center',
        marginTop:30
    },
    view: {
        justifyContent:"center"
    }

})
export default Screen1
//export default connect (Screen1)

Eu estou muito perdido com redux, já sei pra que serve, etc, mas não consigo entender direito como faz. Então nesse meu contexto, como eu poderia pegar essa função mudaTexto() que precisa saber o state para funcionar e passo ela pra uma pasta src/Actions por exemplo? Como precisa ficar o código da action, do reducer e da screen nesse caso? Eu sei que é pedir muito, mas vai deixar um estagiário que conseguiu começar na área agora mto feliz kkkk Qro chegar lá segunda já entendendo disso kkkk
Raphael

Raphael

Responder

Post mais votado

26/06/2019

Fala Raphael, tranquilo cara? Antes de mais nada, gostaria de deixar claro que sou estudante também. Se eu te apresentar algum conceito errado, que alguém me corrija. Bom vamos organizar as ideias por aqui. Vi que você está meio perdido, então vou tentar esclarecer antes de te propor uma solução.
Primeiramente, pense no redux como um compartilhador de estados entre componentes que só deve ser usado QUANDO NECESSÁRIO. Digo isso pois o Facebook criou o React pensando em simplificar as coisas com um framework altamente escalável. Mas o estado nativo do react é lido em árvore (passado de pai para filho) e isso dificulta quando você precisa interagir o estado de um componente superior com um componente de nível mais baixo.
O redux veio para resolver esse problema centralizando o estado (state) em algo que chamamos de store. Todo componente que tiver interessado nesse estado, precisa de conectar a store (através do método connect importado do react-redux) pra ter acesso a determinado estado. No redux, para alterar o estado, precisamos fazer dispatch de algo que chamamos de action creators. WTF, como assim? Veja: https://miro.medium.com/max/1838/0*95tBOgxEPQAVq9YO.png

Vamos a um exemplo prático. Imagine que você tem dois componentes (A e B):

ComponentA.js
import react from "react"
import { View, Text } from "react-native"

export default class ComponentA extends React.Component {
   constructor(props) {
      this.state = { text: "" }
   }

   changeText(newValue) { 
       this.setState({ ...this.state, text: newValue })
   }

   render(){
      <View>
         <Text>{this.state.text}</Text>
      </View>
   }
}


ComponentB.js
import react from "react"
import { View, Text } from "react-native"

export default class ComponentB extends React.Component {
   render(){
      <View>
         <Text>Nada por enquanto</Text>
      </View>
   }
}


Repare que no componente A nós temos uma propriedade de estado denominada text e um método que pode alterar esse estado. Imagine agora que eu quero que o componente B enxergue o estado do componente A e, ainda mais, quero que o B seja capaz de MODIFICAR o estado de A também. Com o react puro, poderíamos colocar o B dentro de A e passar o método de alteração de estado e o próprio estado via props. Mas isso nos limita. Nesse caso, B ficaria aninhado em A, e nós não queremos isso. O que queremos é flexibilidade, ou seja, em qualquer canto da aplicação, podemos fazer com que B enxergue e altere o estado de A. Para isso, precisamos fazer o seguinte:

ComponentA.js
import react from "react"
import { View, Text } from "react-native"
import bindActionCreators from "redux"
import connect from "react-redux"

import { changeText } from "./componentAactions"

class ComponentA extends React.Component {
   render(){
      <View>
         <Text>{this.props.text}</Text>
      </View>
   }
}

const mapStateToProps = state => ({ text: state.componentA.text })
const mapDisptachToProps = dispatch => bindActionCreators({ changeText }, dispatch)

export default connect(mapStateToProps, mapDisptachToProps)(ComponentA)


ComponentB.js
import react from "react"
import { View, Text } from "react-native"
import bindActionCreators from "redux"
import connect from "react-redux"

import { changeText } from "./componentAactions"

class ComponentB extends React.Component {
   componentDidMount() {
      this.props.changeText("Novo valor do texto")
   }

   componentDidUpdate() {
   
   }

   render(){
      <View>
         <Text>{this.props.text}</Text>
      </View>
   }
}

const mapStateToProps = state => ({ text: state.componentA.text })
const mapDisptachToProps = dispatch => bindActionCreators({ changeText }, dispatch)

export default connect(mapStateToProps, mapDisptachToProps)(ComponentB)


componentAactions.js
export function changeText(newValue) {
   return {
      type: "TEXT_CHANGED",
      payload: newValue
   }
}


componentAreducer.js
const INITIAL_STATE = {
   text: ""
}

export default (state = INITIAL_STATE, action) {
   switch(action.type) {
      case "CHANGED_TEXT":
         return { ...state, text: action.payload }
      case default:
         return state
   }
}


Repare que agora o state não está mais presente no componente e sim em um reducer. E a action também foi para um arquivo separado.
O que fizemos simplesmente, ou não tão simples assim (rsrs), foi conectar os dois componentes à store do REDUX decorando-os. As duas constantes mapStateToProps e mapDispatchToProps como o próprio nome diz, servem para MAPEAR, ou seja: "REACT, PEGUE AS PROPRIEDADES DO MEU STATE E MAPEIE PARA QUE MEU COMPONENTE POSSA USAR" e "REACT, PEGUE AS ACTIONS E MAPEIE PARA QUE MEU COMPONENTE POSSA DISPARÁ-LAS QUANDO EU QUISER ALTERAR ALGO NO ESTADO".

** Actions creators servem para CRIAR ações que serão DISPARADAS posteriormente
** Reducers servem para alterar parte do estado

Veja que importamos o actionCreator changeText() em ambos os componentes. Nesse caso, os dois componentes podem mudar o text. Quando disparamos a action no componentDidMount() do componentB, o redux se encarrega de chamar todos os REDUCERS e passa como argumento para esses reducers o TIPO da action e o seu valor de peso / novo valor do estado (payload). Assim, o framework sabe quando e exatamente o que alterar no estado. Alterando o estado, o texto é renderizado novamente em A e B.

Para que o código acima funcione, é necessário configurá-lo no index.js da sua aplicação. Fica como tarefa pra você fazer isso.

--------------------------------------------------------------------

Agora vamos ao seu caso. Você deve ter percebido que o redux tem uma curva de aprendizado maior. Não é do dia pra noite, requer prática e o mínimo de dedicação. Ele é um pouco mais verboso e só vale a pena usá-lo em casos de apps que vão crescer, ou, quando há necessidade de compartilhar o estado entre componentes distantes. Então, pra esses simples componente que você mostrou, não é necessário na minha opinião usar o Redux.

Abraços.

Gabriel

Gabriel
Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar