在本节中,我们将学习如何在 React 应用程序中实现 Redux。这里,我们提供了一个连接 Redux 和 React 的简单示例。
步骤 1:创建React 项目
使用create-react-app命令创建一个新的 React 项目。我选择的项目名称为:“ reactproject ”。现在,安装Redux和React-Redux。
javatpoint@root:~/Desktop$ npx create-react-app reactproject javatpoint@root:~/Desktop/reactproject$ npm install redux react-redux --save
步骤2:创建文件和文件夹
在此步骤中,我们需要为操作、reducer、组件和容器创建文件夹和文件。创建文件夹和文件后,我们的项目如下图所示。
步骤 3:Actions
它使用 ' type ' 属性来告知应发送到Store 的数据。在此文件夹中,我们将创建两个文件:index.js和index.spec.js。在这里,我们创建了一个动作创建器,它返回我们的动作并为每个创建的项目设置一个id 。
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 }) }) })
第 4:Reducers
我们知道,Actions 只会触发应用程序中的更改,而 Reducers 会指定这些更改。Reducer 是一个函数,它接受两个参数“Action”和“State”来计算并返回更新的状态。它从“Actions”读取有效负载,然后通过 State 相应地更新“Store”。
在给定的文件中,每个 Reducer 管理其自己的全局状态部分。每个 Reducer 的状态参数都不同,并且与其管理的“状态”部分相对应。当应用程序变大时,我们可以将 Reducer 拆分为单独的文件,并使它们完全独立并管理不同的数据域。
在这里,我们使用“combineReducers”辅助函数来添加我们将来可能使用的任何新 Reducers。
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
步骤 5:组件
它是一个展示组件,关注事物的外观,例如标记、样式。它接收数据并通过 props 专门调用回调。它不知道数据来自哪里或如何更改数据。它只呈现提供给它们的内容。
App.js
它是呈现 UI 中所有内容的根组件。
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
它告诉用户在哪里更改当前可见的待办事项。
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
这是一个带有回调的链接。
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
TodoList.js
它是一个显示可见待办事项{id,文本,已完成}的列表。
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
步骤6:容器
它是一个容器组件,与数据获取、状态更新等工作方式有关。它为展示组件或其他容器组件提供数据和行为。它使用 Redux State 读取数据并调度 Redux Action 来更新数据。
添加Todo.js
它包含带有添加(提交)按钮的输入字段。
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
它代表当前的可见性过滤器并呈现一个链接。
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
它过滤待办事项并呈现待办事项列表。
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)
Step-7:Store
所有容器组件都需要访问 Redux Store 才能订阅它。为此,我们需要将其(store)作为 prop 传递给每个容器组件。然而,这很繁琐。因此,我们建议使用名为
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') )
输出
当我们执行该应用程序时,它会给出如下屏幕的输出。
现在,我们将能够在列表中添加项目。
好啦,就分享这么多吧。
网友评论文明上网理性发言 已有0人参与
发表评论: