组件树:

    这样划分方式当然是没错的。但是在组件的实现上有些问题,我们之前并没有太多地考虑复用性问题。所以现在可以看看 的 CommentInput 组件,你会发现它里面有一些 LocalStorage 操作:

    它是一个依赖 LocalStorage 数据的 Smart 组件。如果别的地方想使用这个组件,但是数据却不是从 LocalStorage 里面取的,而是从服务器取的,那么这个组件就没法复用了。

    幸运的是,我们发现其实 CommentListComment 本来就是 Dumb 组件,直接把它们俩移动到 components 目录下即可。而 CommentInput 就需要好好重构一下了。我们把它里面和 LocalStorage 操作相关的代码全部删除,让它从 props 获取数据,变成一个 Dumb 组件,然后移动到 src/components/CommentInput.js 文件内:

    1. import React, { Component } from 'react'
    2. import PropTypes from 'prop-types'
    3. export default class CommentInput extends Component {
    4. static propTypes = {
    5. username: PropTypes.any,
    6. onSubmit: PropTypes.func,
    7. onUserNameInputBlur: PropTypes.func
    8. }
    9. static defaultProps = {
    10. username: ''
    11. }
    12. constructor (props) {
    13. super(props)
    14. username: props.username, // 从 props 上取 username 字段
    15. }
    16. }
    17. componentDidMount () {
    18. this.textarea.focus()
    19. }
    20. handleUsernameBlur (event) {
    21. if (this.props.onUserNameInputBlur) {
    22. this.props.onUserNameInputBlur(event.target.value)
    23. }
    24. }
    25. handleUsernameChange (event) {
    26. this.setState({
    27. username: event.target.value
    28. })
    29. }
    30. handleContentChange (event) {
    31. content: event.target.value
    32. })
    33. }
    34. handleSubmit () {
    35. if (this.props.onSubmit) {
    36. this.props.onSubmit({
    37. username: this.state.username,
    38. content: this.state.content,
    39. createdTime: +new Date()
    40. })
    41. }
    42. this.setState({ content: '' })
    43. }
    44. render () {
    45. // render 方法保持不变
    46. // ...
    47. }
    48. }

    其实改动不多。原来 CommentInput 需要从 LocalStorage 中获取 username 字段,现在让它从 props 里面去取;而原来用户名的输入框 blur 的时候需要保存 username 到 LocalStorage 的行为也通过 props.onUserNameInputBlur 传递到上层去做。现在 CommentInput 是一个 Dumb 组件了,它的所有渲染操作都只依赖于 props 来完成。


    因为第三方评论工具有问题,对本章节有任何疑问的朋友可以移步到 React.js 小书的论坛 发帖,我会回答大家的疑问。