【问题标题】:Props is still empty after mapStateToPropsmapStateToProps 后 Props 仍然为空
【发布时间】:2019-01-18 00:27:28
【问题描述】:

我正在使用 mern stack 应用程序,当我尝试将状态传递给特定组件的 props 时出现错误。

我得到错误:

TypeError: Cannot read property 'items' of undefined

D:/Mohammed/project/mern-app/client/src/components/ShoppingList.js:19
  16 |        this.props.deleteItem(id);
  17 |    }
  18 | 
> 19 |    render() {
     | ^  20 |        const { items } = this.props.item;
  21 |    return (
  22 |      <div>

这是我的代码的仓库: https://github.com/mohamedsaad4/mern-app

这里是 mern-app/client/src/App.js

import React, { Component } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Navbars } from './components/Navbar';
import { ShoppingList } from './components/ShoppingList';
import { Provider } from 'react-redux';
import store from './store';

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <div className="App">
          <Navbars />
          <ShoppingList />
        </div>
      </Provider>
    );
  }
}

export default App;

这里是 mern-app/client/src/components/ShoppingList.js

import React, { Component } from 'react';
import { Container, ListGroup, ListGroupItem, Button } from 'reactstrap';
import {  CSSTransition, TransitionGroup } from 'react-transition-group';
import { connect } from 'react-redux';
import { getItems, deleteItem } from '../actions/itemActions';
import PropTypes from 'prop-types';


export class ShoppingList extends Component {

    componentDidMount() {
        this.props.getItems();
    }

    deleteClick = (id) => {
        this.props.deleteItem(id);
    }

    render() {
        const { items } = this.props.item;
    return (
      <div>
          <Container>
              <ListGroup>
                  <TransitionGroup className="shopping-list">
                    {
                        items.map(({id, name}) => (
                            <CSSTransition key={id} timeout={500} classNames='fade'>
                                <ListGroupItem>
                                    <Button
                                        className='remove-btn'
                                        color='danger'
                                        size='sm'
                                        onClick={this.deleteClick.bind(this, id)}
                                    >&times;</Button>
                                     {name}
                                </ListGroupItem>
                            </CSSTransition>
                        ))
                    }
                  </TransitionGroup>
              </ListGroup>
          </Container>
      </div>
    )
  }
}

ShoppingList.propTypes = {
    getItems: PropTypes.func.isRequired,
    item: PropTypes.object.isRequired
}

const mapStateToProps = (state) => {
    return {
        item: state.item
    }
}

export default connect(mapStateToProps, { getItems, deleteItem })(ShoppingList);

这里是 mern-app/client/src/store.js

import { compose, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const initialState = {};

const middleware = [thunk];

const store = createStore(rootReducer, initialState, compose(
   applyMiddleware(...middleware)
));

export default store;

这里是 mern-app/client/src/actions/itemActions.js

import { GET_ITEMS, ADD_ITEM, DELETE_ITEM } from './types';

export const getItems =  () => {
    return {
        type: GET_ITEMS
    };
};

export const deleteItem =  (id) => {
    return {
        type: DELETE_ITEM,
        payload: id
    };
};

这里是 mern-app/client/src/actions/types.js

export const GET_ITEMS = 'GET_ITEMS';
export const ADD_ITEM = 'ADD_ITEM';
export const DELETE_ITEM = 'DELETE_ITEM';

这里是 mern-app/client/src/reducers/index.js

import { combineReducers } from 'redux';
import itemReducer from './itemReducer';

export default combineReducers({
    item: itemReducer
});

最后是 mern-app/client/src/reducers/itemReducer.js

import uuid from 'uuid';
import { GET_ITEMS, ADD_ITEM, DELETE_ITEM } from '../actions/types';

const initialState = {
    items: [
        {id: uuid(), name: 'ali'},
        {id: uuid(), name: 'amgad'},
        {id: uuid(), name: 'nour'},
    ]
};

export default function(state = initialState, action) {
    switch(action.type) {
        case GET_ITEMS:
            return {
                ...state
            }
        case DELETE_ITEM:
            return {
                ...state,
                items: state.items.filter(item => item.id !== action.payload)
            }
        default:
            return state;
    }
}

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    您的连接组件导入和导出不匹配。

    在ShoppingList.js,你有:

    // Named export
    export class ShoppingList extends Component {}
    
    // Default export
    export default connect(mapStateToProps, { getItems, deleteItem })(ShoppingList);
    

    在App.js,你有:

    // Named import
    import { ShoppingList } from './components/ShoppingList';
    

    所以,您正在导入ShoppingList 的未连接 版本并使用它。

    将其更改为默认导入,以便您获得组件的连接版本,它应该可以工作:

    import ShoppingList from './components/ShoppingList';
    

    【讨论】:

    • 是的,它有效!非常感谢 @markerikson 的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    相关资源
    最近更新 更多