React.js/Redux + 드래그 앤 드롭

가장 최근 프로젝트인 'GreenHouse'에서 사용자는 집에 식물을 얼마든지 포함할 수 있는 공간을 관리합니다. 이 프로젝트의 목표 중 하나는 유동적인 사용자 경험을 제공하기 위해 최대한 많은 대화형 기능을 통합하는 것이었습니다. 끌어서 놓기는 이 목표를 향한 큰 발걸음이었습니다. 나는 공간 사이에 식물을 끌어다 놓고 포함된 방 구성 요소를 적절하게 업데이트할 수 있기를 원했고, 이를 달성하는 것은 내 Redux 빌드와 통합하기가 비교적 간단했습니다.

PlantCard와 SpaceCard라는 두 가지 기본 구성 요소로 시작합니다. 저는 클래스 구성 요소에 더 익숙하지만 이 기능은 기능적 구성 요소를 사용하여 달성할 수도 있습니다.

첫째, PlantCard

## PlantCard.js

import React, { Component } from 'react';

class PlantCard extends Component {

  # unrelated PlantCard functionality goes up here

  render() {
    return(
      <ul className='plant-card'>
        # plant information goes here
      </ul>
    );
  }
}

export default PlantCard


...그러면 SpaceCard

## SpaceCard.js

import React, { Component } from 'react';

class SpaceCard extends Component {

  # unrelated SpaceCard functionality goes up here

  render() {
    return(
      <div className='space-card'>
        <div className='space-info'>
          # space info goes here
        </div>
        <div classname='space-plants'>
          {this.props.plants.map(plant => <PlantCard plant={plant} />)}
        </div>
      </div>
    );
  }
}

export default SpaceCard


기본 구성 요소가 설정되면 끌어서 놓기 기능을 구축할 수 있습니다. 먼저, 우리는 PlantCard에게 끌리는 것에 대해 알려줄 것입니다.

dragStart = event = {
  const plant = JSON.stringify(this.props.plant);
  event.dataTransfer.setData('plant', plant);
}


마우스 버튼을 누른 채 Plant 구성 요소에서 멀리 끌면 구성 요소의 plant prop이 키워드 plant 아래의 DataTransfer 객체에 저장됩니다.

이상한 그래픽 문제를 방지하기 위한 안전 장치로 이 기능을 PlantCard 클래스 구성 요소에 추가할 수도 있습니다.

dragOver = event => {
  event.stopPropagation();
}


마지막으로 이러한 기능을 구성 요소에 의해 렌더링되는 HTML 요소에 연결하고 'draggable' 특성에 'true'를 할당합니다.

render () {
  return(
    <ul
      className='plant-card'
      onDragStart={this.dragStart}
      onDragOver={this.dragOver}
      draggable='true'
    >
      # Plant information goes here
    </ul>
  );
}




떨어뜨린 PlantCard를 수신하는 SpaceCard의 기능에 대해서는 이전과 유사한 패턴을 따를 것입니다.
먼저 주목해야 할 점은 수신 요소에 '끌기 중' 기능이 없으면 D&D가 작동하지 않으므로 의도하지 않은 동작에 대한 안전 장치로 일반event.preventDefault()으로 정의하겠습니다.

dragOver = event => {
  event.preventDefault();
}


다음은 작업의 발전소입니다. 여기서 우리는 실제로 응용 프로그램에 식물의 연결된 공간을 놓을 공간으로 변경하도록 지시합니다.

drop = event => {
  event.preventDefault();
  const plant = JSON.parse(event.dataTransfer.getData('plant'));
  plant.spaceId = this.props.space.id;
  this.props.editPlant(plant);
}


거기에 많은 것이 있으므로 한 줄씩 분해하겠습니다. 우리는 원하지 않는 문제에 대한 모든 것을 포착하기 위해 기본 preventDefault()로 다시 시작합니다. 다음으로, DataTransfer 개체에서 해당 '식물' 키워드를 요청하고 변수로 설정하여 저장한 식물 데이터에 액세스합니다. 우리는 그 변수를 가져와 필요한 속성(이 경우 spaceId)을 변경한 다음 redux 스토어에서 제공하는 디스패치 함수에 전달합니다. 간결함을 위해 구성 요소를 상점에 연결하는 과정을 생략했습니다.

마지막으로 몇 가지 변경 사항을 추가하여 HTML에 모든 것을 알릴 수 있습니다.

render() {
  return(
    <div
      className='space-card'
      onDrop={this.drop}
      onDragOver={this.dragOver}
    >
      <div className='space-info'>
        # space info goes here
      </div>
      <div classname='space-plants'>
        {this.props.plants.map(plant => <PlantCard plant={plant} />)}
      </div>
    </div>
  );
}


결국, 다음과 같이 약간의 춤을 출 수 있는 것으로 끝납니다.

좋은 웹페이지 즐겨찾기