Rate this post

Redux là thư viện ngôn ngữ JavaScript open source được sử dụng để quản lý application state. React thường sử dụng Redux để làm giao diện của người dùng. Nó được giới thiệu cho cộng đồng bởi Dan Abramov và Andrew Clark vào năm 2015.

Các bài viết liên quan:

React Redux là official React binding cho Redux. Nó cho phép các component React lấy dữ liệu từ Redux Store và gửi các Action đến Store để cập nhật dữ liệu. Redux giúp các ứng dụng mở rộng dễ dàng bằng cách cung cấp các phương thức quản lý state thông qua unidirectional data flow model(mô hình luồng dữ liệu một chiều). Về mặt định nghĩa thì React Redux rất đơn giản. Nó đăng ký vào Store Redux, kiểm tra xem data mà component của bạn có thay đổi hay không và render lại các component.

Redux được lấy cảm hứng từ Flux. Redux đã nghiên cứu kiến ​​trúc Flux và tối ưu Flux cho đơn giản hơn.

  • Redux không có khái niệm Dispatcher.
  • Redux có một Store duy nhất trong khi Flux có nhiều Store.
  • Các đối tượng Action sẽ được Store tiếp nhận và xử lý trực tiếp.

Tại sao sử dụng React Redux?

Lý do chính để sử dụng React Redux là:

  • React Redux là ràng buộc giao diện người dùng chính thức cho Ứng dụng React. Nó được cập nhật với bất kỳ thay đổi API nào để đảm bảo rằng các component React của bạn hoạt động như mong đợi.
  • Nó khuyến khích kiến ​​trúc ‘React’ tốt.
  • Nó thực hiện nhiều tối ưu hóa hiệu suất bên trong, cho phép các component chỉ hiển thị lại khi nó thực sự cần.

Kiến trúc Redux

Các component của kiến ​​trúc Redux được giải thích bên dưới.

STORE: store là nơi liệt kê toàn bộ trạng thái ứng dụng của bạn. Nó quản lý trạng thái của ứng dụng và có chức năng điều phối (hành động). Nó giống như một bộ não chịu trách nhiệm về tất cả các bộ phận chuyển động trong Redux.

ACTION: Action được gửi hoặc gửi đi từ chế độ xem là các trọng tải có thể được đọc bởi Bộ giảm thiểu. Nó là một đối tượng thuần túy được tạo ra để lưu trữ thông tin về sự kiện của người dùng. Nó bao gồm thông tin như loại hành động, thời gian xảy ra, vị trí xảy ra, tọa độ của nó và trạng thái mà nó muốn thay đổi.

REDUCER: Bộ giảm đọc tải trọng từ các hành động và sau đó cập nhật store thông qua trạng thái tương ứng. Nó là một hàm thuần túy để trả về một trạng thái mới từ trạng thái ban đầu.

Cài đặt Redux

Yêu cầu: React Redux yêu cầu phiên bản React 16.8.3 trở lên.

Để sử dụng React Redux với ứng dụng React, bạn cần cài đặt lệnh dưới đây.

$ npm install redux react-redux --save

Ví dụ về React Redux

Trong phần này, chúng ta sẽ học cách triển khai Redux trong ứng dụng React. Ở đây, chúng tôi cung cấp một ví dụ đơn giản để kết nối Redux và React.

  1. Tạo một dự án React mới bằng lệnh create-react-app. Tôi chọn tên dự án: “reactproject.” Bây giờ, hãy cài đặt Redux và React-Redux.
npx create-react-app reactproject
npm install redux react-redux --save  
  1. Tạo File và thư mục

Trong bước này, chúng ta cần tạo các thư mục và tệp cho các hành động, bộ giảm, component và Containers. Sau khi tạo các thư mục và tệp, dự án của chúng ta sẽ giống như hình dưới đây.

  1. Actions

Nó sử dụng thuộc tính ‘type’ để thông báo về dữ liệu sẽ được gửi đến Store. Trong thư mục này, chúng tôi sẽ tạo hai tệp: index.js và index.spec.js. Ở đây, chúng tôi đã tạo một trình tạo hành động trả lại hành động của chúng tôi và đặt một id cho mọi mục đã tạo.

Index.js

let nextTodoId = 0  
export const addTodo = text => ({  
  type: 'ADD_TODO',  
  id: nextTodoId++,  
  text  
})  
  
export const setVisibilityFilter = filter => ({  
  type: 'SET_VISIBILITY_FILTER',  
  filter  
})  
  
export const toggleTodo = id => ({  
  type: 'TOGGLE_TODO',  
  id  
})  
  
export const VisibilityFilters = {  
  SHOW_ALL: 'SHOW_ALL',  
  SHOW_COMPLETED: 'SHOW_COMPLETED',  
  SHOW_ACTIVE: 'SHOW_ACTIVE'  
}  

Index.spec.js

import * as actions from './index'  
  
describe('todo actions', () => {  
  it('addTodo should create ADD_TODO action', () => {  
    expect(actions.addTodo('Use Redux')).toEqual({  
      type: 'ADD_TODO',  
      id: 0,  
      text: 'Use Redux'  
    })  
  })  
  
  it('setVisibilityFilter should create SET_VISIBILITY_FILTER action', () => {  
    expect(actions.setVisibilityFilter('active')).toEqual({  
      type: 'SET_VISIBILITY_FILTER',  
      filter: 'active'  
    })  
  })  
  
  it('toggleTodo should create TOGGLE_TODO action', () => {  
    expect(actions.toggleTodo(1)).toEqual({  
      type: 'TOGGLE_TODO',  
      id: 1  
    })  
  })  
})  
  1. Reducers

Như chúng ta đã biết, Hành động chỉ kích hoạt các thay đổi trong ứng dụng và Trình giảm bớt chỉ định những thay đổi đó. Giảm tốc là một hàm nhận hai tham số ‘Hành động’ và ‘Trạng thái’ để tính toán và trả về một Trạng thái đã cập nhật. Nó đọc các trọng tải từ ‘Hành động’ và sau đó cập nhật ‘stores’ thông qua Bang cho phù hợp.

Trong các tệp đã cho, mỗi Bộ giảm tốc quản lý phần riêng của Trạng thái toàn cầu. Tham số Trạng thái khác nhau đối với mỗi Hộp giảm tốc và tương ứng với phần ‘Trạng thái’ mà nó quản lý. Khi ứng dụng trở nên lớn hơn, chúng tôi có thể chia Reducers thành các tệp riêng biệt và giữ chúng hoàn toàn độc lập và quản lý các miền dữ liệu khác nhau.

Ở đây, chúng tôi đang sử dụng chức năng trợ giúp ‘connectReducers’ để thêm bất kỳ Bộ giảm thiểu mới nào mà chúng tôi có thể sử dụng trong tương lai.

index.js

import { combineReducers } from 'redux'  
import todos from './todos'  
import visibilityFilter from './visibilityFilter'  
  
export default combineReducers({  
  todos,  
  visibilityFilter  
})  

Todos.js

const todos = (state = [], action) => {  
  switch (action.type) {  
    case 'ADD_TODO':  
      return [  
        ...state,  
        {  
          id: action.id,  
          text: action.text,  
          completed: false  
        }  
      ]  
    case 'TOGGLE_TODO':  
      return state.map(todo =>  
        (todo.id === action.id)  
          ? {...todo, completed: !todo.completed}  
          : todo  
      )  
    default:  
      return state  
  }  
}  
export default todos  

Todos.spec.js

import todos from './todos'  
  
describe('todos reducer', () => {  
  it('should handle initial state', () => {  
    expect(  
      todos(undefined, {})  
    ).toEqual([])  
  })  
  
  it('should handle ADD_TODO', () => {  
    expect(  
      todos([], {  
        type: 'ADD_TODO',  
        text: 'Run the tests',  
        id: 0  
      })  
    ).toEqual([  
      {  
        text: 'Run the tests',  
        completed: false,  
        id: 0  
      }  
    ])  
  
    expect(  
      todos([  
        {  
          text: 'Run the tests',  
          completed: false,  
          id: 0  
        }  
      ], {  
        type: 'ADD_TODO',  
        text: 'Use Redux',  
        id: 1  
      })  
    ).toEqual([  
      {  
        text: 'Run the tests',  
        completed: false,  
        id: 0  
      }, {  
        text: 'Use Redux',  
        completed: false,  
        id: 1  
      }  
    ])  
  
    expect(  
      todos([  
        {  
          text: 'Run the tests',  
          completed: false,  
          id: 0  
        }, {  
          text: 'Use Redux',  
          completed: false,  
          id: 1  
        }  
      ], {  
        type: 'ADD_TODO',  
        text: 'Fix the tests',  
        id: 2  
      })  
    ).toEqual([  
      {  
        text: 'Run the tests',  
        completed: false,  
        id: 0  
      }, {  
        text: 'Use Redux',  
        completed: false,  
        id: 1  
      }, {  
        text: 'Fix the tests',  
        completed: false,  
        id: 2  
      }  
    ])  
  })  
  
  it('should handle TOGGLE_TODO', () => {  
    expect(  
      todos([  
        {  
          text: 'Run the tests',  
          completed: false,  
          id: 1  
        }, {  
          text: 'Use Redux',  
          completed: false,  
          id: 0  
        }  
      ], {  
        type: 'TOGGLE_TODO',  
        id: 1  
      })  
    ).toEqual([  
      {  
        text: 'Run the tests',  
        completed: true,  
        id: 1  
      }, {  
        text: 'Use Redux',  
        completed: false,  
        id: 0  
      }  
    ])  
  })  
})  

VisibilityFilter.js

import { VisibilityFilters } from '../actions'  
  
const visibilityFilter = (state = VisibilityFilters.SHOW_ALL, action) => {  
  switch (action.type) {  
    case 'SET_VISIBILITY_FILTER':  
      return action.filter  
    default:  
      return state  
  }  
}  
export default visibilityFilter  
  1. Các component

Nó là một component trình bày, liên quan đến cách mọi thứ trông như thế nào, chẳng hạn như đánh dấu, kiểu dáng. Nó nhận dữ liệu và gọi lại độc quyền thông qua đạo cụ. Nó không biết dữ liệu đến từ đâu hoặc làm thế nào để thay đổi nó. Nó chỉ hiển thị những gì được trao cho họ.

App.js

Nó là component gốc hiển thị mọi thứ trong giao diện người dùng.

import React from 'react'  
import Footer from './Footer'  
import AddTodo from '../containers/AddTodo'  
import VisibleTodoList from '../containers/VisibleTodoList'  
  
const App = () => (  
  <div>  
    <AddTodo />  
    <VisibleTodoList />  
    <Footer />  
  </div>  
)  
export default App  

Footer.js

Nó cho biết nơi người dùng thay đổi các công việc hiện có thể nhìn thấy.

import React from 'react'  
import FilterLink from '../containers/FilterLink'  
import { VisibilityFilters } from '../actions'  
  
const Footer = () => (  
  <p>  
    Show: <FilterLink filter={VisibilityFilters.SHOW_ALL}>All</FilterLink>  
    {', '}  
    <FilterLink filter={VisibilityFilters.SHOW_ACTIVE}>Active</FilterLink>  
    {', '}  
    <FilterLink filter={VisibilityFilters.SHOW_COMPLETED}>Completed</FilterLink>  
  </p>  
)  
export default Footer  

Link.js

Nó là một liên kết với một callbacks.

import React from 'react'  
import PropTypes from 'prop-types'  
  
const Link = ({ active, children, onClick }) => {  
  if (active) {  
    return <span>{children}</span>  
  }  
  
  return (  
    <a  
      href=""  
      onClick={e => {  
        e.preventDefault()  
        onClick()  
      }}  
    >  
      {children}  
    </a>  
  )  
}  
  
Link.propTypes = {  
  active: PropTypes.bool.isRequired,  
  children: PropTypes.node.isRequired,  
  onClick: PropTypes.func.isRequired  
}  
  
export default Link  

Todo.js

import React from 'react'  
import PropTypes from 'prop-types'  
  
const Todo = ({ onClick, completed, text }) => (  
  <li  
    onClick={onClick}  
    style={{  
      textDecoration: completed ? 'line-through' : 'none'  
    }}  
  >  
    {text}  
  </li>  
)  
  
Todo.propTypes = {  
  onClick: PropTypes.func.isRequired,  
  completed: PropTypes.bool.isRequired,  
  text: PropTypes.string.isRequired  
}  
  
export default Todo  

Nó đại diện cho một mục công việc duy nhất hiển thị văn bản.

TodoList.js

Đây là danh sách để hiển thị các việc cần làm {id, text, complete} có thể nhìn thấy được.

import React from 'react'  
import PropTypes from 'prop-types'  
import Todo from './Todo'  
  
const TodoList = ({ todos, onTodoClick }) => (  
  <ul>  
    {todos.map((todo, index) => (  
      <Todo key={index} {...todo} onClick={() => onTodoClick(index)} />  
    ))}  
  </ul>  
)  
  
TodoList.propTypes = {  
  todos: PropTypes.arrayOf(  
    PropTypes.shape({  
      id: PropTypes.number.isRequired,  
      completed: PropTypes.bool.isRequired,  
      text: PropTypes.string.isRequired  
    }).isRequired  
  ).isRequired,  
  onTodoClick: PropTypes.func.isRequired  
}  
export default TodoList  
  1.  Containers

Nó là một component Containers liên quan đến cách thức hoạt động của những thứ như tìm nạp dữ liệu, cập nhật Trạng thái. Nó cung cấp dữ liệu và hành vi cho các component trình bày hoặc các component chứa khác. Nó sử dụng Trạng thái Redux để đọc dữ liệu và gửi Hành động Redux để cập nhật dữ liệu.

AddTodo.js

Nó chứa trường đầu vào có nút ADD (gửi).

import React from 'react'  
import { connect } from 'react-redux'  
import { addTodo } from '../actions'  
  
const AddTodo = ({ dispatch }) => {  
  let input  
  
  return (  
    <div>  
      <form onSubmit={e => {  
        e.preventDefault()  
        if (!input.value.trim()) {  
          return  
        }  
        dispatch(addTodo(input.value))  
        input.value = ''  
      }}>  
        <input ref={node => input = node} />  
        <button type="submit">  
          Add Todo  
        </button>  
      </form>  
    </div>  
  )  
}  
export default connect()(AddTodo)  

FilterLink.js

Nó đại diện cho bộ lọc khả năng hiển thị hiện tại và hiển thị một liên kết.

import { connect } from 'react-redux'  
import { setVisibilityFilter } from '../actions'  
import Link from '../components/Link'  
  
const mapStateToProps = (state, ownProps) => ({  
  active: ownProps.filter === state.visibilityFilter  
})  
  
const mapDispatchToProps = (dispatch, ownProps) => ({  
  onClick: () => dispatch(setVisibilityFilter(ownProps.filter))  
})  
  
export default connect(  
  mapStateToProps,  
  mapDispatchToProps  
)(Link)  

VisibleTodoList.js

Nó lọc các việc cần làm và hiển thị một TodoList.

import { connect } from 'react-redux'  
import { toggleTodo } from '../actions'  
import TodoList from '../components/TodoList'  
import { VisibilityFilters } from '../actions'  
  
const getVisibleTodos = (todos, filter) => {  
  switch (filter) {  
    case VisibilityFilters.SHOW_ALL:  
      return todos  
    case VisibilityFilters.SHOW_COMPLETED:  
      return todos.filter(t => t.completed)  
    case VisibilityFilters.SHOW_ACTIVE:  
      return todos.filter(t => !t.completed)  
    default:  
      throw new Error('Unknown filter: ' + filter)  
  }  
}  
  
const mapStateToProps = state => ({  
  todos: getVisibleTodos(state.todos, state.visibilityFilter)  
})  
  
const mapDispatchToProps = dispatch => ({  
  toggleTodo: id => dispatch(toggleTodo(id))  
})  
  
export default connect(  
  mapStateToProps,  
  mapDispatchToProps  
)(TodoList)  
  1. stores

Tất cả các component Containers cần có quyền truy cập vào Redux Store để đăng ký với nó. Đối với điều này, chúng ta cần chuyển nó (lưu trữ) làm chỗ dựa cho mọi component container. Tuy nhiên, nó trở nên tẻ nhạt. Vì vậy, chúng tôi khuyên bạn nên sử dụng component React Redux đặc biệt được gọi là component làm cho stores có sẵn cho tất cả các component Containers mà không cần chuyển nó một cách rõ ràng. Nó được sử dụng một lần khi bạn kết xuất component gốc.

index.js

import React from 'react'  
import { render } from 'react-dom'  
import { createStore } from 'redux'  
import { Provider } from 'react-redux'  
import App from './components/App'  
import rootReducer from './reducers'  
  
const store = createStore(rootReducer)  
  
render(  
  <Provider store={store}>  
    <App />  
  </Provider>,  
  document.getElementById('root')  
)  

Khi chúng tôi thực thi ứng dụng, nó sẽ đưa ra kết quả như màn hình bên dưới.

Bây giờ, chúng tôi sẽ có thể thêm các mục trong danh sách.

Leave a Reply

Call now
%d bloggers like this: