【问题标题】:Implementing React Redux实现 React Redux
【发布时间】:2016-03-28 21:49:18
【问题描述】:

我正在慢慢学习 React,同时也在学习用 Redux 来实现它。但我似乎遇到了障碍。这就是我到目前为止所拥有的。

/index.jsx

import './main.css'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App.jsx'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import ShoppingList from './reducers/reducer'

let store = createStore(ShoppingList)

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

/actions/items.js

import uuid from 'node-uuid'

export const CREATE_ITEM = 'CREATE_ITEM'
export function createItem(item) {
  return {
    type: CREATE_ITEM,
    item: {
      id: uuid.v4(),
      item,
      checked: false
    }
  }
}

/reducers/reducer.js

import * as types from '../actions/items'
import uuid from 'node-uuid'

const initialState = []

const items = (state = initialState, action) => {
  switch (action.type) {
    case types.CREATE_ITEM:
      return {
        id: uuid.v4(),
        ...item
      }
    default:
      return state;
  }
 }

 export default items

/reducers/index.js
更新:

import { combineReducers } from 'redux'
import items from './reducer'

const ShoppingList = combineReducers({
  items
})

export default ShoppingList

/components/Item.jsx

import React from 'react';
import uuid from 'node-uuid'

export default class Item extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isEditing: false
    }
  }

  render() {
    if(this.state.isEditing) {
      return this.renderEdit();
    }

    return this.renderItem();
  }

  renderEdit = () => {
    return (
      <input type="text"
        ref={(event) => 
          (event ? event.selectionStart = this.props.text.length : null)
        }
        autoFocus={true}
        defaultValue={this.props.text}
        onBlur={this.finishEdit}
        onKeyPress={this.checkEnter} 
      />
    )
  };

  renderDelete = () => {
    return <button onClick={this.props.onDelete}>x</button>;
  };

  renderItem = () => {
    const onDelete = this.props.onDelete;

    return (
      <div onClick={this.edit}>
        <span>{this.props.text}</span>
        {onDelete ? this.renderDelete() : null }
      </div>
    );
  };

  edit = () => {
    this.setState({
      isEditing: true
    });
  };

  checkEnter = (e) => {
    if(e.key === 'Enter') {
      this.finishEdit(e);
    }
  };

  finishEdit = (e) => {
    const value = e.target.value;

    if(this.props.onEdit) {
      this.props.onEdit(value);

      this.setState({
        isEditing: false
      });
    }
  };
}

/components/Items.jsx

import React from 'react';
import Item from './Item.jsx';

export default ({items, onEdit, onDelete}) => {
  return (
    <ul>{items.map(item =>
      <li key={item.id}>
        <Item 
          text={item.text} 
          onEdit={onEdit.bind(null, item.id)}
          onDelete={onDelete.bind(null, item.id)}
        />
      </li>
    )}</ul>
  );
}
//  UPDATE: http://redux.js.org/docs/basics/UsageWithReact.html
// Is this necessary?
const mapStateToProps = (state) => {
  return {
    state
  }
}

Items = connect(
  mapStateToPros
)(Items) // `SyntaxError app/components/Items.jsx: "Items" is read-only`

//////////////////////////////////////
// Also tried it this way. 
//////////////////////////////////////
Items = connect()(Items)
export default Items // same error as above.

也试过了

export default connect(
  state => ({
    items: store.items
  })
)(Items) // `Uncaught TypeError: Cannot read property 'items' of undefined`

更新:

经过多次尝试,Gitter 中的@hedgerh 指出它应该是 state.items。所以解决方案是

export default connect(
  state => ({
    items: state.items
  })
)(Items)

也归功于@azium。

/components/App.jsx

export default class App extends React.Component {
  render() {
    return (
     <div>
        <button onClick={this.addItem}>+</button>
          <Items />
      </div>
    ); 
  } 
}

为了正确实施它,我在这里遗漏了什么?现在它打破了在Items.jsx 中说Uncaught TypeError: Cannot read property 'map' of undefined。我想这是有道理的,因为它似乎没有正确连接。这是应用程序的第一部分,第二部分将允许用户创建许多列表,这些列表包含许多项目。我可能不得不从Item.jsx 中提取方法,因为List.jsx 会做几乎相同的事情。谢谢

【问题讨论】:

  • 您的示例中似乎缺少App.jsx .. items 是如何传递给&lt;Items /&gt; 的?
  • 有些东西需要connected 到你的商店。所以要么你忘了展示那部分,要么你需要在某个地方添加它。
  • 我想这就是我不确定的。我有一个 App.jsx,等一下,我会更新我的问题。 @azium
  • 您是否使用&lt;provider&gt; 将商店传给它的孩子?店铺是怎么传承下来的?你在 App.jsx 中使用 connect 吗?
  • @James111 我正在使用&lt;Provider&gt; 查看我的 index.js。我也经过那里的商店。如果我通过使用Provider 并在那里传递商店来正确理解它,那么我的子组件将可以使用该商店。正确的?现在我如何连接应用程序有点模糊。

标签: reactjs redux react-redux


【解决方案1】:

你错过了connect。这就是东西从你的商店到你的组件的方式。阅读文档 http://redux.js.org/docs/basics/UsageWithReact.html

中的容器部分
import React from 'react'
import Item from './Item.jsx'

import { connect } from 'react-redux'

let Items = ({items, onEdit, onDelete}) => {
  return (
    <ul>{items.map(item =>
      <li key={item.id}>
        <Item 
          text={item.text} 
          onEdit={onEdit.bind(null, item.id)}
          onDelete={onDelete.bind(null, item.id)}
        />
      </li>
      })
  </ul>
  )
}

export default connect(
  state => ({
    items: state.items
  })
)(Items)

此外,您似乎期待从父级传递的 onEditonDelete 函数,但您没有这样做,因此这些函数将是未定义的。

【讨论】:

  • 它说找不到store 我在index.jsx 中创建了我的商店我应该在不同的文件中创建它吗?说stores/store.js 然后在这里导入? @azium
  • 您在index.jsx 中导入了错误的文件。应该是import ShoppingList from './reducers'。目前您正在导入减速器而不调用combineReducers
  • 在您提出更改建议后,我在Items.jsxstore.items 收到Uncaught TypeError: Cannot read property 'items' of undefined
  • 导出默认连接( state => ({ items: state.items }) )(Items)
  • @Diego 我认为在@azium 的示例中,这意味着export default connect(state =&gt; ({ items: store.items}))(Items) 实际上是这样的:export default connect( state =&gt; ({ items: state.items }) )(Items)
猜你喜欢
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 2016-08-06
  • 1970-01-01
  • 2019-05-12
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多