redux todomvc:新项目会发生什么?

时间:2016-11-07 20:48:23

标签: javascript reactjs redux react-redux

我正在学习redux todomvc,并对下面的源代码有一些疑问。欢迎任何评论。感谢。

Q1:为什么没有调用store.dispatch()和store.subscribe()?看来这个例子与data flow introduction有点不同。

第二季度:任何人都能解释一下新项目会发生什么吗? src / index.js,src / containers / App.js,src / components / Header.js,src / components / TodoTextInput.js如何处理新的项目?

问题3:来自(src / containers / App.js)的待办事项和行动在哪里?

问题4:这个状态=== store.getState()(在src / components / TodoTextInput.js中)?

// src/index.js
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './containers/App'
import reducer from './reducers'
import 'todomvc-app-css/index.css'

const store = createStore(reducer)

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

// src/containers/App.js
import React, { PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Header from '../components/Header'
import MainSection from '../components/MainSection'
import * as TodoActions from '../actions'

const App = ({todos, actions}) => (//Q3: where are todos and actions from?
  <div>
    <Header addTodo={actions.addTodo} />  
    <MainSection todos={todos} actions={actions} />
  </div>
)

App.propTypes = {
  todos: PropTypes.array.isRequired,
  actions: PropTypes.object.isRequired
}

const mapStateToProps = state => ({
  todos: state.todos
})

const mapDispatchToProps = dispatch => ({
    actions: bindActionCreators(TodoActions, dispatch)
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)


// src/components/Header.js
import React, { PropTypes, Component } from 'react'
import TodoTextInput from './TodoTextInput'

export default class Header extends Component {
  static propTypes = {
    addTodo: PropTypes.func.isRequired
  }

  handleSave = text => {
    if (text.length !== 0) {
      this.props.addTodo(text)
    }
  }

  render() {
    return (
      <header className="header">
        <h1>todos</h1>
        <TodoTextInput newTodo// where is it from?
                       onSave={this.handleSave}
                       placeholder="What needs to be done?" />
      </header>
    )
  }
}

// src/components/TodoTextInput.js
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'

export default class TodoTextInput extends Component {
  static propTypes = {
    onSave: PropTypes.func.isRequired,
    text: PropTypes.string,
    placeholder: PropTypes.string,
    editing: PropTypes.bool,
    newTodo: PropTypes.bool
  }

  state = {//Q4: this state === store.getState()?
    text: this.props.text || ''
  }

  handleSubmit = e => {
    const text = e.target.value.trim()
    if (e.which === 13) {
      this.props.onSave(text)
      if (this.props.newTodo) {
        this.setState({ text: '' })
      }
    }
  }

  handleChange = e => {
    this.setState({ text: e.target.value })
  }

  handleBlur = e => {
    if (!this.props.newTodo) {
      this.props.onSave(e.target.value)
    }
  }

  render() {
    return (
      <input className={
        classnames({
          edit: this.props.editing,
          'new-todo': this.props.newTodo
        })}
        type="text"
        placeholder={this.props.placeholder}
        autoFocus="true"
        value={this.state.text}
        onBlur={this.handleBlur}
        onChange={this.handleChange}
        onKeyDown={this.handleSubmit} />
    )
  }
}

// src/components/TodoItem.js
import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import TodoTextInput from './TodoTextInput'

export default class TodoItem extends Component {
  static propTypes = {
    todo: PropTypes.object.isRequired,
    editTodo: PropTypes.func.isRequired,
    deleteTodo: PropTypes.func.isRequired,
    completeTodo: PropTypes.func.isRequired
  }

  state = {
    editing: false
  }

  handleDoubleClick = () => {
    this.setState({ editing: true })
  }

  handleSave = (id, text) => {
    if (text.length === 0) {
      this.props.deleteTodo(id)
    } else {
      this.props.editTodo(id, text)
    }
    this.setState({ editing: false })
  }

  render() {
    const { todo, completeTodo, deleteTodo } = this.props

    let element
    if (this.state.editing) {
      element = (
        <TodoTextInput text={todo.text}
                       editing={this.state.editing}
                       onSave={(text) => this.handleSave(todo.id, text)} />
      )
    } else {
      element = (
        <div className="view">
          <input className="toggle"
                 type="checkbox"
                 checked={todo.completed}
                 onChange={() => completeTodo(todo.id)} />
          <label onDoubleClick={this.handleDoubleClick}>
            {todo.text}
          </label>
          <button className="destroy"
                  onClick={() => deleteTodo(todo.id)} />
        </div>
      )
    }

    return (
      <li className={classnames({
        completed: todo.completed,
        editing: this.state.editing
      })}>
        {element}
      </li>
    )
  }
}

1 个答案:

答案 0 :(得分:0)

  

Q1为什么没有调用store.dispatch()和store.subscribe()?

因为&#39;容器&#39;。在redux中,容器是订阅商店中的更改的组件。这是通过Redux的mapStateToPropsmapDispatchToProps完成的,最后是container file

内的connect函数调用

connect函数在内部调用store.subscribe

  

Q2:有人可以解释新项目会发生什么吗?

  1. App容器通过mapDispatchToProps

  2. actions道具传递给App组件
  3. 此道具actions包含addTodo行动,已过去Header

  4. Header组件在addTodosaved

  5. 时调用TextInput操作
  6. 将调度addTodo操作

  7. reducer handles动作并用新项更新状态。商店已更新。

  8. 商店更新会触发App容器重新呈现更新的道具,因为App容器有mapStateToProps

  9. 完成

  10.   

    问题3:(src / containers / App.js)的待办事项和行动在哪里?

    这也是因为Redux的connect功能。它将从mapStateToPropsmapDispatchToProps获取返回值,合并它们并将其作为道具传递给App组件。 todos来自mapStateToPropsactions来自mapDispatchToProps

      

    Q4这个状态=== store.getState()

    不要混淆。 state中的TodoTextInput是React的本机组件状态,与Redux的状态无关。但是,如果您的应用程序中需要一个状态,则需要确定它是应该存在于Redux存储中还是存在于组件本身中。

    如果状态仅与组件本身相关,并且没有其他组件需要知道该状态的状态,则表明它应该存在于组件内部而不是在Redux的存储中。

    TodoTextInput组件中的状态在用户提交更改之前保留用户输入临时值。它非常适合作为组件本身的内部状态。