在Reactjs中使用不同组件使用相同的reducer

时间:2017-02-16 02:31:49

标签: reactjs redux

我的反应应用程序出了问题。我的问题是因为我的两个组件使用相同的reducer和action它们与它们在mapStateToProps中返回的数据冲突并覆盖前一个。有没有办法让他们从reducer返回不同的数据而不是覆盖?

我有这个组件通过api使用getMovieByGroup操作获取数据,它使用api数据成功呈现所需视图,这里是代码:

class HomeBannerIndex extends React.Component {
    constructor(props){
        super(props);
    }

    componentWillMount(){
        this.props.getMovieByGroup("popular");
    }
    renderFirstPopularMovie(){
        if(this.props.data){

            var headerBannerImage = {
                backgroundImage: 'url(' + IMAGE_PATH + '/' + this.props.data.backdrop_path + ')'
            };

            return (
                <div className={styles.homeBanner} style={headerBannerImage}>
                    <div className={styles.homeBannerText}>
                        <Col lg={10} md={10} sm={10} xs={12} className={util.center}>
                            <h1>{ this.props.data.original_title }</h1>
                            <h4>Release Date: { this.props.data.release_date }</h4>
                        </Col>
                    </div>
                    <div className={styles.overlay}></div>
                </div>
            );
        }
    }
    render(){
        return (
                <Grid fluid={true}>
                    <Row>
                        <div className={styles.homeBannerGradient}>
                            { this.renderFirstPopularMovie() }
                        </div>
                    </Row>
                </Grid>
        );
    }
}

function mapStateToProps(state){
    return {
        data: state.film.data[9]
    }
}

export default connect(mapStateToProps, { getMovieByGroup })(HomeBannerIndex);

我还有另一个组件也可以通过api获取相同的getMovieByGroup操作,但它有不同的参数:

class FilmItem extends React.Component {
    constructor(props){
        super(props);
    }

    componentWillMount(){
        this.props.getMovieByGroup("latest");
    }
    render(){
        return (
            <div>
                <Col lg={2} md={4} sm={6} xs={6}>
                    <div className={styles.filmBox}>
                        <Link to="/movies/2"><Image src="http://lorempixel.com/400/400/sports/" responsive /></Link>
                    </div>
                </Col>
                <Clearfix></Clearfix>
            </div>
        );
    }
}

function mapStateToProps(state){
    return {
        data: state.film.data
    }
}

export default connect(mapStateToProps, { getMovieByGroup })(FilmItem);

以下是我的行动中的代码,我在其中调度从API获取的数据:

export function getMovieByGroup(name){
    return function(dispatch){
            console.log(name);
        return axios.get(`${API_URL}/movie/`+name,
            {
                params: {
                    api_key: API_KEY
                }
            }
        )
        .then(response => {
            if(response.status === 200){
                const result = response.data.results;
                dispatch({ type: GET_FILM_SUCCESS, data: result, group: name });
            }
        })
        .catch(error => {
            const result = error.response;
            console.log(result);
            dispatch({ type: GET_FILM_FAILURE, data: result, group: name });
        });
    }
}

这里是减速器:

import { GET_FILM_SUCCESS,GET_FILM_FAILURE } from 'constants/FilmConstant.jsx';

const INITIAL_STATE = {
    data: {}
};

export default (state = INITIAL_STATE, action) => {
    switch(action.type) {
        case GET_FILM_SUCCESS: {
            return { ...state, data: action.data }
        }

        case GET_FILM_FAILURE: {
            return { ...state, data: action.data }
        }
        default: return state;
    }
}

1 个答案:

答案 0 :(得分:0)

在您的reducer中,您可以从data调度组和结果,而不是设置GET_FILM_SUCCESS

export function getMovieByGroup(name){
    return function(dispatch){
        return axios.get(`${API_URL}/movie/`+name,
            {
                params: {
                    api_key: API_KEY
                }
            }
        )
        .then(response => {
            if(response.status === 200){
                dispatch({ type: GET_FILM_SUCCESS, data: { group: name, results: response.data.results } });
            }
        })
        .catch(error => {
            dispatch({ type: GET_FILM_FAILURE, data: { group: name, results: error.response } });
        });
    }
}

然后将以下内容添加到reducer:

import { GET_FILM_SUCCESS,GET_FILM_FAILURE } from 'constants/FilmConstant.jsx';

const INITIAL_STATE = {
    data: {},
    error: {},
};

function processData(initialData, data) {
    let updated = initialData;
    updated[data.group] = data.results;
    return updated;
}

export default (state = INITIAL_STATE, action) => {
    switch(action.type) {
        case GET_FILM_SUCCESS: {
            return { ...state, data: processData(state.data, action.data) }
        }

        case GET_FILM_FAILURE: {
            return { ...state, error: processData(state.data, action.data) }
        }
        default: return state;
    }
}

我希望错误与数据分开处理。如果使用选择器,您将在以后获得更好的控制。