реагировать на изменение слайда в слайдере после нажатия кнопки - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть боковая панель, которую я реализовал следующим образом:

import React from "react";
import './MySidebar.scss';
import {slide as Menu } from 'react-burger-menu'

export class MySidebar extends React.Component {


  constructor(props) {
    super(props);
  }


 changeSlide = (e) => {
   console.log("Clicked " + e.currentTarget.id); //get text content of
 }


  render() {


    return (
        <Menu customCrossIcon={false}>
            <button onClick={((e) => this.changeSlide(e))} className ="menu-item" id="Project1">Project 1</button>
      <button onClick={((e) => this.changeSlide(e))} className ="menu-item" id="Project2">Project 2</button>
        </Menu>
    );
  }
} 

Тогда у меня есть компонент с именем ProjectSliderComponent, который реализует поведение карусели. Это делается так:

import React from "react";
import Slider from "react-slick";
import './project-carousel.component.css';
import { ProjectComponent } from '../project/project.component';
import { LoggerService } from '../../services/logger-service';
import { appConfig } from '../../config';

export class ProjectSliderComponent extends React.Component {

  state = {
    activeSlide: 0,
    timestamp: Date.now()
  }

  constructor(props) {
    super(props);
    this.logger = new LoggerService();

    this.settings = {
      dots: appConfig.dots,
      arrows: false,
      adaptiveHeight: true,
      infinite: appConfig.infinite,
      speed: appConfig.speed,
      autoplay: appConfig.autoplay,
      autoplaySpeed: appConfig.autoplaySpeed,
      slidesToShow: 1,
      slidesToScroll: 1,
      mobileFirst: true,
      className: 'heliosSlide',
      beforeChange: (current, next) => {
        this.setState({ activeSlide: next, timestamp: Date.now() }); 
      }
    };
  }

  render() {

    let i = 0;

    return (
      <div>
      <Slider ref = {c => (this.slider = c)} {...this.settings}>
        {
          this.props.projectListId.data.map(projectId =>
              <ProjectComponent key={projectId} id={projectId} time={this.state.timestamp} originalIndex={ i++ } currentIndex = {this.state.activeSlide}></ProjectComponent>)
        }
      </Slider>
      </div>
    );
  }
}

Компонент ProjectComponent просто определяет макет. Это файл App.js, в который я загружаю компоненты проекта и боковую панель. Я делаю это:

class App extends Component {

  state = {
    projectList: new ProjectListModel(),
    isLoading: true
  }

  constructor(props) {
    super(props);
    this.logger = new LoggerService();
  }



  componentDidMount() {
    let projectService = new ProjectService();
    projectService.getProjectList()
      .then(res => {
        let projectList = new ProjectListModel();
        projectList.data = res.data.data;
        this.setState({ projectList: projectList,
                        isLoading: false });
      })
      .catch(error => {
        this.logger.error(error);
      });
  }



  render() {
      return (
        <div className="App">
          <MySidebar>
            </MySidebar>
          <ProjectSliderComponent projectListId={this.state.projectList}></ProjectSliderComponent>
        </div>
      );
    }
}

export default App;

Что мне нужно сделать, это изменить слайд в зависимости от того, какую кнопку я нажал. Что мне нужно сделать? Есть ли что-то вроде передачи «экземпляра» projectslidercomponent и вызова метода для изменения слайда? Или что-то еще?

Ответы [ 2 ]

2 голосов
/ 29 апреля 2019

В документах о реакции-слике вы можете прочитать о slickGoTo , который является методом компонента Slider.

Поскольку вы уже храните this.slider, вы можете попытаться сделать его доступным в MySidebar и использовать его всякий раз, когда вызывается changeSlide. Скорее всего, вам нужно создать метод changeSlide на верхнем уровне и передать его как свойство вашим компонентам.

1 голос
/ 29 апреля 2019

Чтобы разобраться с этой проблемой, вам нужно создать функцию в родительском компоненте, которая обновляет состояние компонента приложения, и после обновления состояния он будет повторно отображать компонент приложения, а новые реквизиты отправляются в компонент слайдера, который будетскажите, какой слайдер показать.Ниже приведен код: -

В App.js

class App extends Component {

  state = {
    projectList: new ProjectListModel(),
    isLoading: true,
    menuId: 0
  }

  constructor(props) {
    super(props);
    this.logger = new LoggerService();
  }



  componentDidMount() {
    let projectService = new ProjectService();
    projectService.getProjectList()
      .then(res => {
        let projectList = new ProjectListModel();
        projectList.data = res.data.data;
        this.setState({ projectList: projectList,
                        isLoading: false });
      })
      .catch(error => {
        this.logger.error(error);
      });
  }

  ChangeSlide = (menuId) => {
   this.setState({
      menuId //Here you will receive which slide to show and according to that render slides in mySliderbar component
   })
  }



  render() {
      return (
        <div className="App">
          <MySidebar ChangeSlide={this.ChangeSlide} />
          <ProjectSliderComponent menuId={this.state.menuId} projectListId={this.state.projectList}></ProjectSliderComponent>
        </div>
      );
    }
}

export default App;

В mySlidebar

import React from "react";
import './MySidebar.scss';
import {slide as Menu } from 'react-burger-menu'

export class MySidebar extends React.Component {


  constructor(props) {
    super(props);
  }


 changeSlide = (e) => {
   console.log("Clicked " + e.currentTarget.id); //get text content of
   this.props.changeSlide(e.currentTarget.id)
 }


  render() {


    return (
        <Menu customCrossIcon={false}>
            <button onClick={((e) => this.changeSlide(e))} className ="menu-item" id="Project1">Project 1</button>
      <button onClick={((e) => this.changeSlide(e))} className ="menu-item" id="Project2">Project 2</button>
        </Menu>
    );
  }
} 

В компоненте слайдера вы должны слушать, когда приходят новые реквизитыи в соответствии с этим изменением слайд см. componentWillReceiveProps

import React from "react";
import Slider from "react-slick";
import './project-carousel.component.css';
import { ProjectComponent } from '../project/project.component';
import { LoggerService } from '../../services/logger-service';
import { appConfig } from '../../config';

export class ProjectSliderComponent extends React.Component {

  state = {
    activeSlide: 0,
    timestamp: Date.now()
  }

  constructor(props) {
    super(props);
    this.logger = new LoggerService();

    this.settings = {
      dots: appConfig.dots,
      arrows: false,
      adaptiveHeight: true,
      infinite: appConfig.infinite,
      speed: appConfig.speed,
      autoplay: appConfig.autoplay,
      autoplaySpeed: appConfig.autoplaySpeed,
      slidesToShow: 1,
      slidesToScroll: 1,
      mobileFirst: true,
      className: 'heliosSlide',
      beforeChange: (current, next) => {
        this.setState({ activeSlide: next, timestamp: Date.now() }); 
      }
    };
  }
  componentWillReceiveProps(nextProps) {
   if(nextprops.menuId != this.props.menuId){
    this.slider.slickGoTo(nextprops.menuId, true)//use slider instance to 
    //call the function to go to a particular slide.
   }
  }


  render() {

    let i = 0;
    const { menuId } = this.props
    return (
      <div>
      <Slider initialSlide={menuId} ref = {c => (this.slider = c)} {...this.settings}>
        {
          this.props.projectListId.data.map(projectId =>
              <ProjectComponent key={projectId} id={projectId} time={this.state.timestamp} originalIndex={ i++ } currentIndex = {this.state.activeSlide}></ProjectComponent>)
        }
      </Slider>
      </div>
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...