2 minute read

Tags: ,

react-beautiful-dnd

Step by step~~

  • npx create-react-app task-app

  • style package (optional)

    • npm install styled-components
    • npm install @atlaskit/css-reset
  • install: react-beautiful-dnd

    • npm install react-beautiful-dnd
  • 主要長這樣

    • img

實作後 希望可以越來越熟悉~~~

Imgur

  • initial-data.js
const initialData = {
    tasks: {
        'task-1': { id: 'task-1', content: 'Take out the garbage'},
        'task-2': { id: 'task-2', content: 'Watc my favorite show'},
        'task-3': { id: 'task-3', content: 'Charge my phone'},
        'task-4': { id: 'task-4', content: 'Cook dinner'},
    },
    columns: {
        'column-1': {
            id: 'column-1',
            title: 'To do',
            taskIds: ['task-1', 'task-2', 'task-3', 'task-4',],
        }
    },
    columnOrder: ['column-1'],
};

export default initialData;
  • index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { DragDropContext } from 'react-beautiful-dnd';
import initialData from './initial-data';
import Column from './column';
// const App = () => 'Hello World';

class App extends React.Component {
  state = initialData;

  onDragEnd = result => {
    const  { destination, source, draggableId } = result;
    if (!destination) {
      return;
    }

    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }
    
    const column = this.state.columns[source.droppableId];
    const newTaskIds = Array.from(column.taskIds);
    newTaskIds.splice(source.index, 1);
    newTaskIds.splice(destination.index, 0, draggableId);

    const newColumn = {
      ...column,
      taskIds: newTaskIds,
    }

    const newState = {
      ...this.state,
      columns: {
        ...this.state.columns,
        [newColumn.id]: newColumn,
      }
    }

    this.setState(newState);

  }

  /* result example

  const result = {
    draggabledId: 'task-1',
    type: 'Type',
    reason: 'DROP'
    source: {                 // location info
      droppableId: 'column-1',
      index: 0,
    },
    destination: {            // location info
      droppableId: 'column-1',
      index:1
    }
  }
  
  */

  render() {
    return (
      <DragDropContext onDragEnd={this.onDragEnd}>
         {this.state.columnOrder.map((columnId) => {
           const column = this.state.columns[columnId];
           const tasks = column.taskIds.map(taskId => this.state.tasks[taskId])
           
           return <Column key={column.id} column={column} tasks={tasks} />
         })}
      </DragDropContext>
      );
    }
}

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
  • column.jsx
import React, { Component } from 'react'
import styled from 'styled-components';
import Task from './task';
import { Droppable } from 'react-beautiful-dnd';

const Container = styled.div`
    margin: 8px;
    border: 1px solid lightgrey;
    border-raduis: 2px; 
`;
const Title = styled.h3`
    padding: 8px;
`;
const TaskList = styled.div`
    padding: 8px;
`;

export class column extends Component {
    render() {
        return (
           <Container>
               <Title>{this.props.column.title}</Title>
               <Droppable droppableId={this.props.column.id}>
                   {(provided) => (
                    <TaskList
                       ref={provided.innerRef}
                       {...provided.droppableProps}
                    >
                      {this.props.tasks.map((task, index) => <Task key={task.id} task={task} index={index}/>)}
                      {provided.placeholder}
                    </TaskList>
                   )}
               </Droppable>
           </Container>
        );
    }
}

export default column
  • task.jsx
import React, { Component } from 'react'
import styled from 'styled-components';
import { Draggable } from 'react-beautiful-dnd';

const Container = styled.div`
   border: 1px solid lightgrey;
   border-raduis:2px;
   padding: 8px;
   margin-bottom: 8px;
`;

export class Task extends Component {
    render() {
        return (
           <Draggable draggableId={this.props.task.id} index={this.props.index}>
               {provided=> (
                   <Container
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      ref={provided.innerRef}
                    >
                        {this.props.task.content}
                    </Container>
               )}
           </Draggable>
        )
    }
}

export default Task

Other Sources: