返回

Redux重构大实战(下):Footer组件的状态管理

前端

前言

随着 Taro 的不断迭代,小程序开发更加便捷和高效。在本文中,我们将继续使用 Hooks 版的 Redux 重构 Taro 项目,并在此基础上进一步实现项目的状态管理。在上一篇中,我们已经完成了 user 部分的状态管理的重构,受限于篇幅,我们还剩下 Footer 组件部分没有重构。因此,在这一篇中,我们将首先实现 Footer 组件的状态管理的重构,接着我们马上来实现 post 逻辑的状态管理,完成整个项目的重构。有兴趣的同学,可以跟着一起来实现看看哦~

Footer 组件的状态管理重构

Footer 组件是一个简单的组件,它负责显示应用程序的底部导航栏。它的状态非常简单,只有两个属性:activeitemsactive 属性用于指示当前选中的导航栏项,而 items 属性则用于存储导航栏项的列表。

在使用 Hooks 版的 Redux 重构之前,Footer 组件的状态管理代码如下:

import React from 'react'
import { connect } from 'react-redux'

const Footer = (props) => {
  const { active, items } = props

  return (
    <footer className="footer">
      <ul className="footer-nav">
        {items.map((item) => (
          <li key={item.id} className={active === item.id ? 'active' : ''}>
            <a href={item.href}>{item.text}</a>
          </li>
        ))}
      </ul>
    </footer>
  )
}

const mapStateToProps = (state) => ({
  active: state.footer.active,
  items: state.footer.items,
})

export default connect(mapStateToProps)(Footer)

使用 Hooks 版的 Redux 重构后,Footer 组件的状态管理代码如下:

import React from 'react'
import { useSelector } from 'react-redux'

const Footer = () => {
  const active = useSelector((state) => state.footer.active)
  const items = useSelector((state) => state.footer.items)

  return (
    <footer className="footer">
      <ul className="footer-nav">
        {items.map((item) => (
          <li key={item.id} className={active === item.id ? 'active' : ''}>
            <a href={item.href}>{item.text}</a>
          </li>
        ))}
      </ul>
    </footer>
  )
}

export default Footer

可以看出,使用 Hooks 版的 Redux 重构后,Footer 组件的状态管理代码更加简洁和易读。同时,它也与 React 的函数式组件语法更加一致。

post 逻辑的状态管理重构

接下来,我们来实现 post 逻辑的状态管理的重构。post 逻辑是 Taro 项目中比较复杂的一部分,它负责管理帖子列表的显示和编辑。它的状态也比较复杂,包括帖子列表、当前选中的帖子、以及帖子的编辑状态等。

在使用 Hooks 版的 Redux 重构之前,post 逻辑的状态管理代码如下:

import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux'

const PostList = (props) => {
  const [posts, setPosts] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((res) => res.json())
      .then((data) => {
        setPosts(data)
        setLoading(false)
      })
      .catch((err) => {
        setError(err)
        setLoading(false)
      })
  }, [])

  const handleEditPost = (post) => {
    props.dispatch({ type: 'SET_EDIT_POST', post })
  }

  const handleDeletePost = (post) => {
    props.dispatch({ type: 'DELETE_POST', post })
  }

  return (
    <ul className="post-list">
      {loading ? (
        <li>Loading...</li>
      ) : error ? (
        <li>Error: {error.message}</li>
      ) : (
        posts.map((post) => (
          <li key={post.id}>
            <a href="#" onClick={() => handleEditPost(post)}>{post.title}</a>
            <button onClick={() => handleDeletePost(post)}>Delete</button>
          </li>
        ))
      )}
    </ul>
  )
}

const PostEditor = (props) => {
  const [title, setTitle] = useState(props.post ? props.post.title : '')
  const [body, setBody] = useState(props.post ? props.post.body : '')

  const handleSavePost = () => {
    props.dispatch({ type: 'SAVE_POST', post: { id: props.post ? props.post.id : null, title, body } })
  }

  return (
    <form className="post-editor">
      <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
      <textarea value={body} onChange={(e) => setBody(e.target.value)}></textarea>
      <button onClick={handleSavePost}>Save</button>
    </form>
  )
}

const mapStateToProps = (state) => ({
  posts: state.post.posts,
  editPost: state.post.editPost,
})

export default connect(mapStateToProps)(PostList)
export default connect(mapStateToProps)(PostEditor)

使用 Hooks 版的 Redux 重构后,post 逻辑的状态管理代码如下:

import React, { useState, useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'

const PostList = () => {
  const posts = useSelector((state) => state.post.posts)
  const loading = useSelector((state) => state.post.loading)
  const error = useSelector((state) => state.post.error)
  const dispatch = useDispatch()

  useEffect(() => {
    dispatch({ type: 'FETCH_POSTS' })
  }, [])

  const handleEditPost = (post) => {
    dispatch({ type: 'SET_EDIT_POST', post })
  }

  const handleDeletePost = (post) => {
    dispatch({ type: 'DELETE_POST', post })
  }

  return (
    <ul className="post-list">
      {loading ? (
        <li>Loading...</li>
      ) : error ? (
        <li>Error: {error.message}</li>
      ) : (
        posts.map((post) => (
          <li key={post.id}>
            <a href="#" onClick={() => handleEditPost(post)}>{post.title}</a>
            <button onClick={() => handleDeletePost(post)}>Delete</button>
          </li>
        ))
      )}
    </ul>
  )
}

const PostEditor = () => {
  const editPost = useSelector((state) => state.post.editPost)
  const dispatch = useDispatch()

  const [title, setTitle] = useState(editPost ? editPost.title : '')
  const [body, setBody] = useState(editPost ? editPost.body : '')

  const handleSavePost = () => {
    dispatch({ type: 'SAVE_POST', post: { id: editPost ? editPost.id : null, title, body } })
  }

  return (
    <form className="post-editor">
      <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
      <textarea value={body} onChange={(e) => setBody(e.target.value)}></textarea>
      <button onClick={handleSavePost}>Save</button>
    </form>
  )
}

export default PostList
export default PostEditor

可以看出,使用 Hooks 版的 Redux 重构后,post 逻辑的状态管理代码更加简洁和易读。同时,它也与 React 的函数式组件语法更加一致。

总结

通过本文,我们完成了 Taro 项目的状态管理的重构。在重构过程中,我们使用了 Hooks 版的 Redux,使代码更加简洁和易读。同时,我们也遵循了 React 的函数式组件语法,使代码更加一致和易于维护。

希望