ReactJS通过redux ajax将道具传递给孩子

时间:2017-05-22 07:51:43

标签: ajax reactjs react-redux

我有一个带有redux的reactjs组件,它将异步通道传递给子组件。

在子组件中,我尝试捕获componentDidMount中的数据,但不知何故也不起作用,但子组件正在渲染。

这是我的父组件

import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as slidesActions from '../../actions/slidesActions';
import Slider from '../Partials/Slider'
import _ from 'underscore';


class HomePage extends React.Component {

    constructor(props) {
        super(props);
    }

    componentDidMount() {
        this.props.actions.getSlides()
    }

    componentWillMount() {
        const {slides} = this.props;
    }

    render() {
        const {slides} = this.props;

        return (
            <div className="homePage">
                <Slider columns={1}  slides={slides} />
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        slides: state.slides
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(slidesActions, dispatch)
    };
}


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

这里是我的子组件,我试图通过幻灯片道具但是空的

import React from 'react';
import _ from 'underscore';
import Hammer from 'hammerjs';


class Slider extends React.Component {

    constructor(props) {
        super(props)
        this.updatePosition = this.updatePosition.bind(this);
        this.next = this.next.bind(this);
        this.prev = this.prev.bind(this);

        this.state = {
            images: [],
            slidesLength: null,
            currentPosition: 0,
            slideTransform: 0,
            interval: null
        };
    }

    next() {
        const currentPosition = this.updatePosition(this.state.currentPosition - 10);
        this.setState({ currentPosition });

    }

    prev() {
        //TODO: work on logic
        if( this.state.currentPosition !== 0) {
            const currentPosition = this.updatePosition(this.state.currentPosition + 10);
            this.setState({currentPosition});
        }
    }


    componentDidMount() {
        //here I try set a state variable on slides 
        let {slides} = this.props
        let slidesLength = slides.length 
        this.setState({slidesLength})

        this.hammer = Hammer(this._slider)
        this.hammer.on('swipeleft', this.next);
        this.hammer.on('swiperight', this.prev);
    }

    componentWillUnmount() {
        this.hammer.off('swipeleft', this.next)
        this.hammer.off('swiperight', this.prev)
    }

    updatePosition(nextPosition) {
        const { visibleItems, currentPosition } = this.state;
        return nextPosition;
    }

    render() {
        let {slides, columns} = this.props
        let {currentPosition} = this.state
        let sliderNavigation = null

        //TODO: this should go to slides actions
        let slider = _.map(slides, function (slide) {
            let Background = slide.featured_image_url.full;
            if(slide.status === 'publish')
                return <div className="slide" id={slide.id}  key={slide.id}><div className="Img" style={{ backgroundImage: `url(${Background})` }} data-src={slide.featured_image_url.full}></div></div>
        });

        if(slides.length > 1 ) {

          sliderNavigation =   <ul className="slider__navigation">
                <li data-slide="prev" className="" onClick={this.prev}>previous</li>
                <li data-slide="next" className="" onClick={this.next}>next</li>
            </ul>
        }

        return <div ref={
            (el) => this._slider = el
        } className="slider-attached"
                    data-navigation="true"
                    data-columns={columns}
                    data-dimensions="auto"
                    data-slides={slides.length}>
                    <div className="slides" style={{ transform: `translate(${currentPosition}%, 0px)`, left : 0 }}> {slider} </div>

                    {sliderNavigation}
            </div>
    }
}

export default Slider;

在这里我有我的滑块

的动作
import * as types from './actionTypes';
import axios from 'axios';
import _ from 'underscore';


//TODO: this should be accessed from DataService
if (process.env.NODE_ENV === 'development') {
    var slidesEndPoint = 'http://dev.server/wp-json/wp/v2/slides';
} else {
    var slidesEndPoint = 'http://prod.server/wp-json/wp/v2/slides';
}

export function getSlides () {
    return dispatch => {
        dispatch(setLoadingState()); // Show a loading spinner

        axios.get(slidesEndPoint)
            .then(function (response) {
                dispatch(setSlides(response.data))
                dispatch(doneFetchingData(response.data))
            })
            /*.error((response) => {
                dispatch(showError(response.data))
            })*/

    }
}


function setSlides(data) {
    return {
        type: types.SLIDES_SUCCESS,
        slides: data
    }
}


function setLoadingState() {
    return {
        type: types.SHOW_SPINNER,
        loaded: false
    }
}

function doneFetchingData(data) {
    return {
        type: types.HIDE_SPINNER,
        loaded: true,
        slides: data
    }
}

function showError() {
    return {
        type: types.SHOW_ERROR,
        loaded: false,
        error: 'error'
    }
}

2 个答案:

答案 0 :(得分:1)

原因是,componentDidMount只会在初​​始渲染之后被调用一次,因为您在获取数据之前异步提取数据,因此Slider组件将被渲染。

所以你需要使用componentwillreceiveprops生命周期方法。

<强> componentDidMount:

  

componentDidMount()在组件出现后立即调用   安装。需要DOM节点的初始化应该放在这里。如果你   需要从远程端点加载数据,这是一个好地方   实例化网络请求。在这种方法中设置状态会   触发重新渲染。

<强> componentWillReceiveProps

  

在安装的组件之前调用componentWillReceiveProps()   收到新的道具。如果您需要更新状态以响应   prop更改(例如,重置它),您可以比较this.props   和nextProps并使用this.setState()执行状态转换   这种方法。

像这样写:

componentWillReceiveProps(nextProps){
     if(nextProps.slides){
         let {slides} = nextProps.props
         let slidesLength = slides.length;        

         this.hammer = Hammer(this._slider)
         this.hammer.on('swipeleft', this.next);
         this.hammer.on('swiperight', this.prev);
         this.setState({slidesLength})
     }
}

答案 1 :(得分:1)

据我了解,您正在进行axios调用以获取数据,然后将其设置在稍后返回的reducer中。最初,reducer数据也是空的。现在,因为componentDidMount只被调用一次,并且最初没有数据可能存在,所以您没有看到任何值。使用componentWillReceiveProps功能

componentWillReceiveProps(nextProps) {
        //here I try set a state variable on slides 
        let {slides} = nextProps
        let slidesLength = slides.length 
        this.setState({slidesLength})

        this.hammer = Hammer(this._slider)
        this.hammer.on('swipeleft', this.next);
        this.hammer.on('swiperight', this.prev);
    }