【问题标题】:ReactJS pass props to child via redux ajaxReactJS 通过 redux ajax 将道具传递给孩子
【发布时间】:2017-05-22 07:51:43
【问题描述】:

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

在子组件中,我尝试捕获 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'
    }
}

【问题讨论】:

    标签: ajax reactjs react-redux


    【解决方案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})
         }
    }
    

    【讨论】:

      【解决方案2】:

      据我了解,您正在进行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);
          }
      

      【讨论】:

        猜你喜欢
        • 2017-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-08
        • 2017-08-22
        • 2020-02-19
        • 2018-04-09
        • 2016-03-19
        相关资源
        最近更新 更多