将传递的道具反应到自定义轮播中

React passing props into custom carousel

我正在使用 this.props 然后选择数组来填充我的属性等。有没有更好的方法可以传递道具以缩短 this.props?还有其他人看到这有什么问题吗?还是自动滑动,不是"controlled".

import React, { Component } from 'react';
import { Carousel as BSCarousel } from 'react-bootstrap';

class Carousel extends Component {
  getInitialState() {
    return {
      index: 0,
      direction: null,
    };
  }

  handleSelect(selectedIndex, e) {
    this.setState({
      index: selectedIndex,
      direction: e.direction,
    });
  }

  render() {
    return (
      <BSCarousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
        <BSCarousel.Item>
          <img alt={this.props.alt} src={this.props.image} />
          <BSCarousel.Caption>
            <h3>{this.props.heading}</h3>
            <p>{this.props.caption}</p>
          </BSCarousel.Caption>
        </BSCarousel.Item>
      </BSCarousel>
    );
  }
}

export default Carousel;

编辑

import React, { Component } from 'react';
import { Carousel as BSCarousel } from 'react-bootstrap';

class Carousel extends Component {
  constructor(props) {
    super(props);

    this.state = { index: 0, direction: null };

    this.handleSelect = this.handleSelect.bind(this);
  }

  render() {
    const { alt, image, heading, caption } = this.props;

    return (
      <BSCarousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
        <BSCarousel.Item>
          <img alt={alt} src={image} />
          <BSCarousel.Caption>
            <h3>{heading}</h3>
            <p>{caption}</p>
          </BSCarousel.Caption>
        </BSCarousel.Item>
      </BSCarousel>
    );
  }
}

export default Carousel;

Is there a better way where I can pass props to shorten from this.props?

使用解构

render() {
    const {alt, image, heading, caption} = this.props

    return (
      <BSCarousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
        <BSCarousel.Item>
          <img alt={alt} src={image} />
          <BSCarousel.Caption>
            <h3>{heading}</h3>
            <p>{caption}</p>
          </BSCarousel.Caption>
        </BSCarousel.Item>
      </BSCarousel>
    );
  }

Also does anyone else see anything wrong with this?

您需要先绑定 handleSelect,然后再将其作为回调传递

class Carousel extends Component {
  constructor(props) {
     super(props)

     this.state = {/* initial state goes here*/}

     this.handleSelect = this.handleSelect.bind(this)
  }

  ... rest of your code

你正在混合es5 and es6写一个React组件,es6中没有getInitialState方法。使用 constructor 初始化 state 值。

像这样:

class Carousel extends Component {

   constructor() {
       super();
       this.state = {
          index: 0,
          direction: null,
       };
   }

....

您可以在 render 方法中使用 Object destructuring 而不是访问 this.props.key,然后通过键名直接访问值,如下所示:

render(){
   const {alt, image, heading, caption} = this.props;
   console.log(alt, image, heading, caption);
   return (
       <BSCarousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
           <BSCarousel.Item>
               <img alt={alt} src={image} />
               <BSCarousel.Caption>
                  <h3>{heading}</h3>
                  <p>{caption}</p>
               </BSCarousel.Caption>
           </BSCarousel.Item>
       </BSCarousel>
   )
}

检查这个片段它会抛出错误,state is not defined:

class App extends React.Component{

   getInitialState(){
      return {a:1}
   }
   
   render(){
      return <div>Hello: {this.state.a}</div>
   }

}

ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

如果你厌倦了到处看到 this.props,你可以 destructure 这样的道具(与 this.state 相同,或任何其他对象你想分开):

  render() {
    const { alt, heading, image, caption } = this.props;
    return (
      <BSCarousel activeIndex={this.state.index} direction={this.state.direction} onSelect={this.handleSelect}>
        <BSCarousel.Item>
          <img alt={alt} src={image} />
          <BSCarousel.Caption>
            <h3>{heading}</h3>
            <p>{caption}</p>
          </BSCarousel.Caption>
        </BSCarousel.Item>
      </BSCarousel>
    );
  }

因为您使用的是 ES6 类,所以您必须进行不同的设置。

将您的 getInitialState() 函数替换为:

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

你问过是否有办法清理对 this.props 的所有调用,所以这里的大部分答案都提到了解构,这是清理对 [=14= 的调用的好方法],但随后您还询问是否有人认为您的实现有任何问题,并且一些答案指出使用 getInitialState 的过时用法(而不是简单地在构造函数中设置您的初始组件级状态并分配给this.state = {}), 但其他答案没有抓住的事实是您的实施将您的 "Carousel" 限制为仅通过道具 传入的单个项目。 您应该做的是允许自己灵活地通过 props 将任意数量的项目传递给 Carousel 组件。

对我来说,如果它只允许通过 props 传入单个项目,那将是一个高度限制的 Carousel 组件。

这就是我要做的。此实现:

  1. 使用解构来清理所有重复的点符号,
  2. 在构造函数中声明组件级状态,
  3. 允许您通过道具传递任意数量的轮播项目,
  4. 声明一个渲染 Carousel.Item 元素集合的 renderItems() 函数
  5. 调用 CarouselItem 组件,该组件负责创建实际的 Carousel.Item
  6. 确保在构造函数中将任何自定义函数绑定到 this(当您的函数需要引用 this 上下文时需要),
  7. 使用扩展运算符真正清理对 this
  8. 的多次调用

components/Carousel.js

import React, { Component } from 'react';
import { Carousel } from 'react-bootstrap';
import CarouselItem from './CarouselItem'; // 5

class CustomCarousel extends Component {
  constructor(props) {
    super(props);
    this.state = { // 2
      index: 0,
      direction: null,
    };
    this.handleSelect = this.handleSelect.bind(this); // 6
  }

  handleSelect(selectedIndex, e) {
    this.setState({
      index: selectedIndex,
      direction: e.direction,
    });
  }

  generateItems() { // 4
    const { items } = this.props;
    return items.map((item, index) => {
      const active = (index === item.id);
      return (<CarouselItem
        key={`CI${item.id}`}
        active={active}
        direction={this.state.direction}
        {...item} // 7
      />);
    });
  }

  render() {
    return (
      <Carousel
        activeIndex={this.state.index}
        direction={this.state.direction}
        onSelect={this.handleSelect}
      >
        {this.generateItems()}
      </Carousel>
    );
  }
}

export default CustomCarousel;

components/Carousel/CarouselItem.js

import React from 'react';
import { Carousel } from 'react-bootstrap';

const CarouselItem = (props) => {
  const { id, active, direction, image, alt, heading, caption } = props; // 1

  return (
    <Carousel.Item
      index={id}
      active={active}
      direction={direction}
    >
      <img alt={alt} src={image} />
      <Carousel.Caption>
        <h3>{heading}</h3>
        <p>{caption}</p>
      </Carousel.Caption>
    </Carousel.Item>
  );
};

export default CarouselItem;

现在你有一个干净的 Carousel 组件,可以接受任意数量的潜在 "Items"。

您可以这样调用您的自定义轮播:

import CustomCarousel from './path/to/Carousel';

const arrayOfItemObjects = [
  {...},
  {...},
  {...}
];

<CustomCarousel 
   items={arrayOfItemObjects} // 3
/>