- 相對于vue的vuex而言 react的redux確實要復雜許多,并且沒有相對完善適合初學者的檔案,所以學習起來特別困難,這里用一個小例子來寫一下 redux react-redux的簡單用法,事先宣告所有的檔案地址請讀者根據自己的檔案地址寫連接
首先是安裝
// 個人比較喜歡用yarn 不喜歡的可以自行換成npm 或者 cnpm
yarn add redux --save
yarn add react-redux --save
- 在專案中創建store檔案夾 并在其中創建actions.js 和 reducer.js
//redux定義修改state資料的唯一方法就是通過dispatch方法觸發action
// 我們來定義一些待觸發的action
let nextTodoId = 0
const addTodo = text => {
// console.log(text)
return {
type: 'ADD_TODO',
id: nextTodoId++,
text
}
}
const setVisibilityFilter = filter => {
return {
type: 'SET_VISIBILITY_FILTER',
filter
}
}
const toggleTodo = id => {
return {
type: 'TOGGLE_TODO',
id
}
}
export {
addTodo,
setVisibilityFilter,
toggleTodo
}
接下來撰寫reducer
// reducer可以撰寫自己想存盤的資料及方法 因為資料或者方法可能會有很多 所以可以使用
// combineReducers 方法將資料和方法合并在一起方便將來創建存盤庫
import { combineReducers } from 'redux'
// 生成要保存的todos資料 這里因為任務是集合 所以回傳的是陣列
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
}
}
// 這里多寫一個方法 提供給合并演示用 這里并未使用該方法 只為了方便讀者理解combineReducers的作用
const visibilityFilter = (state = 'SHOW_ALL', action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
const todoApp = combineReducers({
todos,
visibilityFilter
})
export default todoApp
寫好reducer就可以創建自己的倉庫了
- 在 store檔案夾下創建一個index.js檔案, 代碼如下
import React from 'react';
// 從redux匯入創建倉庫的方法
import { createStore } from 'redux';
// 匯入撰寫完成的reducer
import todo from './reducer'
const store = createStore(todo)
export default store
warn這里參考檔案中的一句話技術上講,容器組件就是使用 store.subscribe() 從 Redux state 樹中讀取部分資料,并通過 props 來把這些資料提供給要渲染的組件,你可以手工來開發容器組件,但建議使用 React Redux 庫的 connect() 方法來生成,這個方法做了性能優化來避免很多不必要的重復渲染,(這樣你就不必為了性能而手動實作 React 性能優化建議 中的 shouldComponentUpdate 方法,)
使用 connect() 前,需要先定義 mapStateToProps 這個函式來指定如何把當前 Redux store state 映射到展示組件的 props 中,例如,VisibleTodoList 需要計算傳到 TodoList 中的 todos,所以定義了根據 state.visibilityFilter 來過濾 state.todos 的方法,并在 mapStateToProps 中使用,
其實就是說我們可以通過connect來寫傳入自己想要傳遞給組件的資料 而不是每次都用整個倉庫這樣并不友好
方法的就比如下面這種
import { connect } from 'react-redux'
import { toggleTodo } from '../../store/actions'
import Tasks from '../tasks/Tasks'
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
case 'SHOW_ALL':
default:
return todos
}
}
const mapStateToProps = state => {
// console.log(state) // 所有的reducer方法
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = dispatch => {
return {
onTodoClick: id => {
dispatch(toggleTodo(id))
}
}
}
// connect的引數將作為資料傳遞給tasks組件
// 這里表示的是將todos和onToDoClick傳入tasks組件的props中
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(Tasks)
export default VisibleTodoList
- 至此我們的redux倉庫就創建完成了 接下來就是使用了
在專案的入口檔案index.js中
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// provider可以魔法性的讓所有的組件都訪問到store
import { Provider } from 'react-redux'
// 匯入定義好的store
import store from './store/index'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
準備作業完畢 接下來就是組件了
//首先是App.js
import React from 'react'
import Header from './components/header/Header'
import Tasks from './components/tasks/Tasks'
import Visiable from './components/visiable/visiable'
class App extends React.Component {
render() {
return (
<div className="App">
<Header />
<Visiable />
</div>
);
}
}
export default App;
//這個是header組件
import React from 'react'
import './Header.css'
import { connect } from 'react-redux'
import { addTodo } from '../../store/actions'
class Header extends React.Component {
constructor(props) {
super()
}
add = (e) => {
if(e.keyCode === 13) {
this.props.dispatch(addTodo(e.target.value))
}
}
render() {
return (
<div className="header_box">
<div><span className="title">ToDoList</span><input placeholder="添加todo" onKeyUp={this.add}/></div>
</div>
)
}
}
Header = connect()(Header)
export default Header
···
```javascript
//這里是任務組件
import React,{Component} from 'react';
import './Task.css';
import { PropTypes } from 'prop-types'; // 定義接收的值的型別
class Tasks extends Component {
render() {
return (
<div className="task_list">
<h3>{this.props.title}</h3>
<ul>
{this.props.todos.map(todo => {
return <li
className="item_task"
key={todo.id}
onClick={() => this.props.onTodoClick(todo.id)}
style={
{
textDecoration: todo.completed ? 'line-through' : 'none'
}
}
>
<div>
<input type="checkbox" />
<div>{todo.text}</div>
</div>
<span className="del">-</span>
</li>
})}
</ul>
</div>
);
}
}
Tasks.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 Tasks;
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/233534.html
標籤:其他
