mapStateToProps不更新道具 - React dnd和redux

时间:2018-04-08 14:38:00

标签: javascript reactjs redux react-redux react-dnd

我正在处理小型拖放应用。
我希望能够在页面刷新后坚持它的状态,所以我想到了使用Redux并坚持选择的键。
我使用React-dnd并且已经存在拖放逻辑。在某些事件(例如丢弃)上,我添加了要调度的操作。这些操作会更改redux状态并将所选项目从一个列表移动到另一个列表。我可以看到redux商店中的变化,但它们不会出现在用户界面中。即使Redux状态发生变化,道具基本上也不会改变。在使用相同选择器的同时,我收到了UI的正确初始状态。

我的问题:道具不会更新状态变化。

我的问题:为什么以及我做错了什么?

MaveISeenItContainer.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import HTML5Backend from 'react-dnd-html5-backend';
import {DragDropContext} from 'react-dnd';

import * as actions from '../../actions/MoviesActions';

import HaveISeenItComponent from './HaveISeenItComponent';
import {getSelectedMovies, getAllMovies, getStatus} from '../../reducers/MoviesReducer';

let HaveISeenItContainer = props => <HaveISeenItComponent {...props} />;

const mapDispatchToProps = dispatch => ({
    getMovies: () => dispatch(actions.getMovies.request()),
    selectMovie: values => dispatch(actions.selectMovie.request(values)),
    removeMovie:  values => dispatch(actions.removeMovie.request(values))
});

const mapStateToProps = state => ({
    allMovies: getAllMovies(state),
    selectedMovies: getSelectedMovies(state),
    status: getStatus(state)
});

HaveISeenItContainer = DragDropContext(HTML5Backend)(HaveISeenItContainer);

export default connect(mapStateToProps, mapDispatchToProps)(HaveISeenItContainer);

HaveISeenItComponent.js

class HaveISeenItComponent extends Component {
    componentDidMount(id, index) {
        if (this.props.status !== 'SUCCESS') {
            this.props.getMovies();
        }
    }

    handleMovieSelect = (id, card) => {
        this.props.selectMovie({listId: id, id: card.id, card: card})
    };

    handleMovieRemove = (id, index) => {
        this.props.removeMovie({listId: id, cardId: index});
    };

    render() {
        const {selectedMovies, allMovies} = this.props;
        let availableMoviesList = null;
        let moviesToBeSeenList = null;
        if (this.props.status === 'SUCCESS') {
            const allMoviesList = _.map(allMovies, (value, key) => ({
                    id: key,
                    title: value.title
                })
            );
            const selectedMoviesList = _.map(selectedMovies, (value, key) => ({
                    id: key,
                    title: value.title
                })
            );
            availableMoviesList = <List
                id={1}
                list={allMoviesList}
                onMovieRemove={this.handleMovieRemove}
                onMovieSelect={this.handleMovieSelect}
            />;
            moviesToBeSeenList = <List
                id={2}
                list={selectedMoviesList}
                onMovieRemove={this.handleMovieRemove}
                onMovieSelect={this.handleMovieSelect}
            />;
        }
        return (
            <div className={styles.mainComponent}>
                {moviesToBeSeenList}
                {availableMoviesList}
            </div>
        );
    }
}

HaveISeenItComponent.propTypes = {
    getMovies: PropTypes.func
};

export default HaveISeenItComponent;

List.js

class List extends Component {
    constructor(props) {
        super(props);
        this.state = {cards: props.list};
    }

    pushCard(card) {
        const {onMovieSelect, id} = this.props;
        onMovieSelect(id, card);
    }

    removeCard(index) {
        const {onMovieRemove, id} = this.props;
        onMovieRemove(id, index);
    }

    moveCard(dragIndex, hoverIndex) {
        const {cards} = this.state;
        const dragCard = cards[dragIndex];
        this.setState(update(this.state, {
            cards: {
                $splice: [
                    [dragIndex, 1],
                    [hoverIndex, 0, dragCard]
                ]
            }
        }));
    }

    render() {
        const {cards} = this.state;
        const {canDrop, isOver, connectDropTarget} = this.props;
        const isActive = canDrop && isOver;
        const style = {
            width: "200px",
            height: "404px",
            border: '1px dashed gray'
        };

        const backgroundColor = isActive ? 'lightgreen' : '#FFF';

        return connectDropTarget(
            <div style={{...style, backgroundColor}}>
                {cards.map((card, i) => {
                    return (
                        <Card
                            key={card.id}
                            index={i}
                            listId={this.props.id}
                            card={card}
                            removeCard={this.removeCard.bind(this)}
                            moveCard={this.moveCard.bind(this)}/>
                    );
                })}
            </div>
        );
    }
}

const cardTarget = {
    drop(props, monitor, component) {
        const {id} = props;
        const sourceObj = monitor.getItem();
        if (id !== sourceObj.listId) component.pushCard(sourceObj.card);
        return {
            listId: id
        };
    }
}

export default DropTarget("Card", cardTarget, (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver(),
    canDrop: monitor.canDrop()
}))(List);

MoviesReducer.js(带基本选择器)

import _ from "lodash";

// import * as actions from 'actions/MoviesActions';
// import { REQUEST_STATUS } from "constants/types";

import * as actions from '../actions/MoviesActions';
import {REQUEST_STATUS} from '../constants/types';
import {LIST_INDEX} from '../constants/constants';

const initialState = {
    allMovies: [],
    selectedMovies: []
};

const MoviesReducer = (state = initialState, action) => {

    switch(action.type){
        case actions.GET_MOVIES.REQUEST:
            return {
                ...state,
                status: REQUEST_STATUS.PENDING
            };

        case actions.GET_MOVIES.SUCCESS:
            return {
                ...state,
                status: REQUEST_STATUS.SUCCESS,
                allMovies: action.response.movies
            };

        case actions.GET_MOVIES.FAILURE:
            return {
                ...state,
                status: REQUEST_STATUS.FAILURE
            };

        case actions.SELECT_MOVIE.REQUEST:
            if(action.values.listId === LIST_INDEX.SELECTED_MOVIES){
                state.selectedMovies.splice(action.values.cardId, 0, action.values.card);
            } else if (action.values.listId === LIST_INDEX.ALL_MOVIES){
                state.allMovies.splice(action.values.cardId, 0, action.values.card);
            }
            return state;

        case actions.REMOVE_MOVIE.REQUEST:
            if(action.values.listId === LIST_INDEX.SELECTED_MOVIES){
                state.selectedMovies.splice(action.values.cardId, 1);
            } else if (action.values.listId === LIST_INDEX.ALL_MOVIES){
                state.allMovies.splice(action.values.cardId, 1);
            }
            return state;

        case actions.MOVE_MOVIE.REQUEST:
            return state;

        default:
            return state;
    }
};

export const MOVIES_STATE_KEY = 'moviesState';

// Selectors
export const getStatus = state => _.get(state, [MOVIES_STATE_KEY, 'status']);

export const getAllMovies = state => _.get(state, [MOVIES_STATE_KEY, 'allMovies']);

export const getSelectedMovies = state => _.get(state, [MOVIES_STATE_KEY, 'selectedMovies']);

export default MoviesReducer;

0 个答案:

没有答案