Hoà chung vào xu thế update cái mới, hôm nay mình sẽ cùng với các bạn làm quen một chút với các loại redux trong ngôn ngữ lập trình react-native.

Để biết react-native là gì mời các bạn ghé qua https://facebook.github.io/react-native/

Để biết Redux là gì thì bạn xem trước khái niệm ở đây http://www.reactnative.com/getting-started-with-react-native-and-redux/

Trong bài viết này mình sẽ giới thiệu tới bạn kiểu Redux mà thường gặp nhất trong react-native đó chính là Redux-Thunk.

Bài viết có sử dụng expo để tạo sample và build app nên bạn xem thêm expo ở https://expo.io/ nếu cần nhé. Muốn hiểu được toàn bộ thì hãy theo dõi hết cả series nhé, mình sẽ upload code full lên github ở bài cuối cùng ^^

Redux-thunk

I. Redux-thunk là gì?

  • Redux-thunk thực chất là tạo ra 1 thunk của react-redux để redux của chúng ta hoạt động ngon hơn mà thôi. (thunk https://en.wikipedia.org/wiki/Thunk) Thunk được hiểu đơn giản là một luồng trong xử lý của react-native
  • Redux-thunk là một thư viện ngoài nhằm xử lý bất đồng bộ khi chúng ta cần đồng bộ giữa các luồng làm việc, giúp ứng dụng hoạt động nhanh hơn, hiệu quả hơn.

Redux Thunk cho phép bạn viết một bộ tạo các action để trả về đối tượng function thay vì 1 hành động cụ thể. Thunk có thể được dùng để delay việc chuyển các action, hoặc đơn giản chỉ là chuyển action nếu đúng điều kiện mà bạn quy định trước đó. Các function inner chứa những method được chuyển theo, trạng thái như là các biến của một method vậy. (Theo như tài liệu  Redux Thunk mô tả)

II. Using

Trong file actions.js, chúng ta update method fetchData và import api như sau:

import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from './constants'
import getPeople from './api'

export function getData() {
  return {
    type: FETCHING_DATA
  }
}

export function getDataSuccess(data) {
  return {
    type: FETCHING_DATA_SUCCESS,
    data,
  }
}

export function getDataFailure() {
  return {
    type: FETCHING_DATA_FAILURE
  }
}

export function fetchData() {
  return (dispatch) => {
    dispatch(getData())
    getPeople()
      .then((data) => {
        dispatch(getDataSuccess(data))
      })
      .catch((err) => console.log('err:', err))
  }
}

Function "fetchData" đóng vai trò như 1 thunk. Khi method này được gọi nó sẽ trả về 1 function có mang theo hành động getData. Sau đó function getPeople sẽ được gọi. Ngay khi method getPeople được thực thi xong, nó sẽ trả về hành động "getDataSuccess".

Tiếp theo, chúng ta update function "configureStore" để áp dụng thunk vào tầng middleware:

import { createStore, applyMiddleware } from 'redux'
import app from './reducers'
import thunk from 'redux-thunk'

export default function configureStore() {
  let store = createStore(app, applyMiddleware(thunk))
  return store
}

trong file configStore.js

III. Sample code

Các bước chúng ta cần phải làm sẽ là:

  1. import applyMiddleware from redux
  2. import thunk from redux-thunk
  3. gọi createStore, đưa vào applyMiddleware với tư cách là đối số thứ 2.

Cuối cùng chúng ta update app.js để sử dụng đố tượng thunk mới này

import React from 'react'
import { TouchableHighlight, View, Text, StyleSheet } from 'react-native'

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

let styles

const App = (props) => {
  const {
    container,
    text,
    button,
    buttonText,
    mainContent
  } = styles

  return (
    <View style={container}>
      <Text style={text}>Redux Examples</Text>
      <TouchableHighlight style={button} onPress={() => props.fetchData()}>
        <Text style={buttonText}>Load Data</Text>
      </TouchableHighlight>
      <View style={mainContent}>
      {
        props.appData.isFetching && <Text>Loading</Text>
      }
      {
        props.appData.data.length ? (
          props.appData.data.map((person, i) => {
            return <View key={i} >
              <Text>Name: {person.name}</Text>
              <Text>Age: {person.age}</Text>
            </View>
          })
        ) : null
      }
      </View>
    </View>
  )
}

styles = StyleSheet.create({
  container: {
    marginTop: 100
  },
  text: {
    textAlign: 'center'
  },
  button: {
    height: 60,
    margin: 10,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#0b7eff'
  },
  buttonText: {
    color: 'white'
  },
  mainContent: {
    margin: 10,
  }
})

function mapStateToProps (state) {
  return {
    appData: state.appData
  }
}

function mapDispatchToProps (dispatch) {
  return {
    fetchData: () => dispatch(fetchData())
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)

Giải thích mớ code ở trên nhé:

  • Chúng ta thêm sự kiện onPress cho đối tượng view TouchableHighlight để gọi method props.fetchData() khi thằng này đc click, press
  • Chúng ta thêm 1 flag đẻ check xem nếu props.appData.isFetching là đúng thì trả về true, nếu không thì phải trả về đối tương view loading
  • Chúng ta thêm 1 flag để check props.appData.data.length liên tục đến khi trả về hết dữ liệu nếu có thì hiện ra tên + tuổi của đối tượng persion

Và giờ khi chúng ta click vào button 'Load Data', chúng ta sẽ nhìn thấy một message 'Loading' và data sẽ được hiện thị 3 giây sau đó.

Kết thúc bài tìm hiểu về Redux-Thunk và cũng hi vọng nó giúp ích được bạn phần nào đó. Trong bài kế tiếp mình sẽ hướng dẫn các bạn sử dụng một loại redux khác đó là "Redux-saga"