试图将react-bootstrap轮播转换为es6和redux

时间:2016-06-24 18:59:34

标签: javascript reactjs ecmascript-6 redux react-bootstrap

我从这里抓取了受控轮播的示例代码:https://react-bootstrap.github.io/components.html#media-content

我尝试使用我的redux设置在es6中运行,但是唉!尽管我付出了崇高的努力,但我仍然遇到以下错误:

SlideShow.js?d20f:20未捕获的TypeError:无法读取属性'方向'未定义的

  1. 我在以下代码中没有约束/做错了什么?
  2. 我可以在愚蠢的组件中处理这样的状态吗?
  3. 为什么那些忘恩负义的英国人离开我们? ;((抱歉刮)
  4. 这是我的愚蠢组件(component / sldeshow.js):

     import React, { Component, PropTypes } from 'react'
    import { List } from 'immutable'
    import { Link } from 'react-router'
    import { Carousel } from 'react-bootstrap'
    
    class Slides extends Component {
    
    constructor(props) {
        super(props)
        this.state = {
          index: 0,
          direction: null
        }
    
        // Bind callback methods to make `this` the correct context.
        this.handleSelect = this.handleSelect.bind(this)
    
      }
    
      handleSelect(selectedIndex, e) {
        alert('selected=' + selectedIndex + ', direction=' + e.direction)
        this.setState({
          index: selectedIndex,
          direction: e.direction
        })
      }
    
      render() {
        return (
          <div>
              {
                //this.props.slides
                this.props.slides.map((s)=> 
                {
                  let id = s.get('id')
                  let title = s.get('title')
                  let image = s.get('image')
                  let alt = s.get('alt')
                  let caption = s.get('caption')
                  return (
    
                    <Carousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect} key={id}>
                      <Carousel.Item>
                        <img width={640} height={480} alt="640x480" src={image} alt={alt}/>
                        <Carousel.Caption>
                          <h3>{title}</h3>
                          <p>{caption}</p>
                        </Carousel.Caption>
                      </Carousel.Item>
                      <Carousel.Item>
                        <img width={640} height={480} alt="640x480" src={image} alt={alt}/>
                        <Carousel.Caption>
                          <h3>{title}</h3>
                          <p>{caption}</p>
                        </Carousel.Caption>
                      </Carousel.Item>
                      <Carousel.Item>
                        <img width={640} height={480} alt="640x480" src={image} alt={alt}/>
                        <Carousel.Caption>
                          <h3>{title}</h3>
                          <p>{caption}</p>
                        </Carousel.Caption>
                      </Carousel.Item>
                    </Carousel>
                       )
              })
            }
          </div>
        )
      }
    }
    
    Slides.propTypes = {
    
      slides: PropTypes.instanceOf(List).isRequired
    }
    
    
    export default Slides
    

    智能容器:

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    import { Link } from 'react-router'
    
    import Slides from 'components/SlideShow'
    import { getInitalSlides } from 'actions/SlidesActions'
    
    
    class Home extends Component {
    
    static fetchData({ store }) {
            return store.dispatch(getInitalSlides())
        }
    
        componentDidMount() {
            this.props.getInitalSlides()
      }
    
      render() {
        return (
          <div className="Home">
            <h1>Home Page</h1>
            <Slides slides={this.props.slides} />
            <div><Link to="/question">to question</Link></div>
            <div><Link to="/posts">to posts</Link></div>
          </div>
        )
      }
    }
    
    function mapStateToProps (state) {
      return { slides: state.slides }
    }
    
    export { Home }
    export default connect(mapStateToProps, { getInitalSlides })(Home)
    

    和示例轮播原始代码:

    const ControlledCarousel = React.createClass({
      getInitialState() {
        return {
          index: 0,
          direction: null
        };
      },
    
      handleSelect(selectedIndex, e) {
        alert('selected=' + selectedIndex + ', direction=' + e.direction);
        this.setState({
          index: selectedIndex,
          direction: e.direction
        });
      },
    
      render() {
        return (
          <Carousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
            <Carousel.Item>
              <img width={900} height={500} alt="900x500" src="/assets/carousel.png"/>
              <Carousel.Caption>
                <h3>First slide label</h3>
                <p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>
              </Carousel.Caption>
            </Carousel.Item>
            <Carousel.Item>
              <img width={900} height={500} alt="900x500" src="/assets/carousel.png"/>
              <Carousel.Caption>
                <h3>Second slide label</h3>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
              </Carousel.Caption>
            </Carousel.Item>
            <Carousel.Item>
              <img width={900} height={500} alt="900x500" src="/assets/carousel.png"/>
              <Carousel.Caption>
                <h3>Third slide label</h3>
                <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>
              </Carousel.Caption>
            </Carousel.Item>
          </Carousel>
        );
      }
    });
    

    P.S 我从api中拉出幻灯片

2 个答案:

答案 0 :(得分:4)

在Carousel组件中尝试onSelect={(i,e)=>this.handleSelect(i,e)}

答案 1 :(得分:0)

为了将来的兴趣,我的代码是带有redux的受控轮播。

请注意,如果您没有定义activeIndex,direction和onSelect 作为组件上的道具,幻灯片显示将起作用(包括上一个和下一个按钮),但您的应用状态不会发生变化,因为您自己并未实际处理该操作,而是由本地操作完成-bootstrap库。

作为一名初学者,我遇到了将这些道具(activeIndex等)从容器传递到组件的问题,但经过一些阅读后,它变得更加清晰。

关键是要了解容器上的this.state和this.props将在组件上可用。请参阅以下代码:

容器name.js:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import store from 'store/configureStore'
import Slides from 'components/SlideShow'
import { getInitalSlides, handleSelect } from 'actions/SlidesActions'

class Home extends Component {

constructor(props) {
    super(props)
    this.state = {
        index: null,
        direction: null
    }
    this.handleSelect = this.handleSelect.bind(this)    

static fetchData({ store }) {
        return store.dispatch(getInitalSlides())
    }

    componentDidMount() {
        this.props.getInitalSlides()
    }

handleSelect(selectedIndex, e) {
        //alert(e)
        this.props.handleSelect(selectedIndex, e)
    }

  render() {
    return (
      <div className="Home">
        <h1>Home Page</h1>
        <Slides 
        slides={this.props.slides}   
        getInitialState={this.state.index} 
        getInitialStateD={this.state.direction}
        slidesControl={this.handleSelect}
        />
        <div><Link to="/question">to question</Link></div>
        <div><Link to="/posts">to posts</Link></div>
      </div>
    )
  }
}

function mapStateToProps (state) {
  const { slides, handleSelect } = state

  return { slides: state.slides, onSelect: state.handleSelect } 
}

export { Home }
export default connect(mapStateToProps { getInitalSlides, handleSelect})(Home)

coponent-name.js:

import React, { Component, PropTypes } from 'react'
import { List } from 'immutable'
import { Link } from 'react-router'
import { Carousel } from 'react-bootstrap'

class Slides extends Component {

//A helper method to feed the list into the render. Prob. could be done much better.

listSlides(s){

    let id = s.get('id')
    let title = s.get('title')
    let image = s.get('image')
    let alt = s.get('alt')
    let caption = s.get('caption')
    return(

                    <Carousel.Item key={id} >
                    <img width={900} height={500} alt={s.get('alt')} src={image} alt={alt}/>
                    <Carousel.Caption>
                      <h3>{title}</h3>
                      <p>{caption}</p>
                    </Carousel.Caption>
                  </Carousel.Item>

              ) 
}

  render() {

    return (
      <Carousel 
      //The name of the method must match the name of the prop on the container parent
      activeIndex={this.props.getInitialState} 
      direction={this.props.getInitialStateD} // <-- Here's a good example
      onSelect={(selectedIndex,e)=>this.props.handleSelect(selectedIndex,e)}
      >
      {
      this.props.slides.map(s=>this.listSlides(s))
    }
    </Carousel>)
  }
}

Slides.propTypes = {

  slides: PropTypes.instanceOf(List).isRequired,
  handleSelect: PropTypes.func.isRequired
}


export default Slides

动作name.js:

export const HANDLE_SELECT = Symbol('HANDLE_SELECT')
export function handleSelect(selectedIndex, e) {
    //alert('selected=' + selectedIndex + ', direction=' + e.direction)

    return {
        index: selectedIndex,
        direction: e.direction,
        type: HANDLE_SELECT
    }
}

减速器-name.js:

import * as ActionType from 'actions/SlidesActions'
import Immutable from 'immutable'

let defaultState = Immutable.fromJS({

    index: null,
  direction: null
})

function handleSelect (state=defaultState, action) {
  switch(action.type) {

    case ActionType.HANDLE_SELECT:
      //alert(action.type + " " + ActionType.HANDLE_SELECT)
      return(state.merge({ updatedHandleSelect: action }))

    default:
      return state
  }
}

export default handleSelect //For the root reducer

最后,在当前时间,使用最新的react-bootstrap版本会出现一个错误(正在修复),它会抛出一个&#34; Uncaught类型的错误:无法读取未定义的属性#34;在受控制的旋转木马上。

以下是您可以回滚版本的github issue,直到修复