Попытка преобразовать карусель реакции-бутстрапа в es6 и redux

Я взял пример кода для управляемой карусели отсюда: https://react-bootstrap.github.io/components.html#media-content

И я пытаюсь заставить его работать в es6 с моей настройкой редукции, но увы! несмотря на все мои благородные усилия, я продолжаю получать следующую ошибку:

SlideShow.js?d20f:20 Uncaught TypeError: Не удается прочитать свойство «направление» неопределенного

  1. Что я не связываю/не делаю неправильно в своем следующем коде?
  2. Могу ли я обрабатывать такое состояние в моем немом компоненте?
  3. Почему, ну почему неблагодарные британцы ушли от нас?? ;( (извините, что поцарапал)

Вот мой тупой компонент (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


person S. Schenk    schedule 24.06.2016    source источник


Ответы (2)


попробуйте onSelect={(i,e)=>this.handleSelect(i,e)} в компоненте "Карусель"

person Kokovin Vladislav    schedule 25.06.2016

Для будущего интереса вот мой код для управляемой карусели с избыточностью.

Обратите внимание, что если вы не определите activeIndex, direction и onSelect в качестве реквизитов компонента, слайд-шоу будет работать (включая кнопки «предыдущий» и «следующий»), но состояние вашего приложения не изменится, поскольку вы фактически не обрабатываете действие самостоятельно, скорее это делается локально библиотекой react-bootstrap.

Как новичок, у меня были проблемы с передачей этих реквизитов (activeIndex и т. д.) из контейнера в компонент, но после некоторого чтения это стало яснее.

Ключевым моментом является понимание того, что this.state и this.props в контейнере будут доступны в компоненте. См. следующий код:

имя-контейнера.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)

имя-компонента.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

имя-действия.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
    }
}

имя-редуктора.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 есть ошибка (исправляется), которая выдает «Ошибка типа Uncaught: невозможно прочитать свойство persist of undefined» на управляемых каруселях.

Вот проблема github, вы можете откатить версию, пока она не будет исправлена

person S. Schenk    schedule 08.07.2016