Rails5、action Cable、React and Rails、React DnD で POC を作成しようとしています。
目的は、trello のようなアプリを作成することですが、採用プロセス用です。
私のフロントはReactJSにあります。
私は 3 つのコンポーネントを持っています。まず、「Candidates」というコンテナを呼び出します。このコンポーネントは、「Card」コンポーネントを呼び出す 2 つの「CardBoard」コンポーネントを呼び出します。
私は、ドラッグ可能なカードとドロップ可能な CardBoard の DnD ライブラリに反応します。カードをボール紙に落とすと、post 呼び出しと websocket (rails5 のアクション ケーブル) を使用して状態を更新します。ポストコールの後にこのメッセージが表示される理由がわかりません:
Uncaught Error: Cannot have two HTML5 backends at the same time.
at HTML5Backend.setup (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:4175), <anonymous>:87:15)
at DragDropManager.handleRefCountChange (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:3566), <anonymous>:52:22)
at Object.dispatch (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:4931), <anonymous>:186:19)
at HandlerRegistry.addSource (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:3594), <anonymous>:104:18)
at registerSource (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:4294), <anonymous>:9:27)
at DragDropContainer.receiveType (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:1793), <anonymous>:146:32)
at DragDropContainer.receiveProps (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:1793), <anonymous>:135:14)
at new DragDropContainer (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:1793), <anonymous>:102:13)
at eval (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:4399), <anonymous>:295:18)
at measureLifeCyclePerf (eval at <anonymous> (webpack-bundle.self-7b1a342….js?body=1:4399), <anonymous>:75:12)
Candidate.jsx =
import React, { PropTypes } from 'react';
import { DragDropContextProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import CardBoard from './CardBoard.jsx';
export default class Candidates extends React.Component {
constructor(props, _railsContext) {
super(props);
this.state = {
candidates: this.props.candidates
}
this.filterByStatus = this.filterByStatus.bind(this)
}
componentDidMount() {
this.setupSubscription();
}
setupSubscription() {
App.candidate = App.cable.subscriptions.create("CandidateChannel", {
connected: () => {
console.log("User connected !")
},
received: (data) => {
this.setState({ candidates: data.candidates })
},
});
}
render() {
return (
<DragDropContextProvider backend={HTML5Backend}>
<div className="recruitment">
{
["À Rencontrer", "Entretien"].map((status, index) => {
return (
<CardBoard candidates={(this.filterByStatus({status}))} status={status} key={index} />
);
})
}
</div>
</DragDropContextProvider>
);
}
}
CardBoard.jsx =
import React, { PropTypes } from 'react';
import Card from './Card.jsx';
import { DropTarget } from 'react-dnd';
import ItemTypes from './ItemTypes';
const cardTarget = {
drop(props: Props) {
var status = ''
if(props.status == "À Rencontrer") {
status = 'to_book'
} else {
status = 'interview'
}
return { status: status };
},
};
@DropTarget(ItemTypes.CARD, cardTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}))
export default class CardBoard extends React.Component<Props> {
constructor(props, _railsContext) {
super(props);
}
render() {
const { canDrop, isOver, connectDropTarget } = this.props;
const isActive = canDrop && isOver;
return connectDropTarget(
<div className={`${this.props.status} ui cards`}>
<h2>{`${this.props.status} (${this.props.candidates.length})`}</h2>
{
(this.props.candidates).map((candidate, index) => {
return <Card candidate={candidate} key={index} />
})
}
{ isActive?
'Release to drop' : 'drag a card here'
}
</div>
);
}
}
Card.jsx=
import React, { PropTypes } from 'react';
import { DragSource } from 'react-dnd';
import ItemTypes from './ItemTypes';
const cardSource = {
beginDrag(props) {
return {
candidate_id: props.candidate.id,
};
},
endDrag(props, monitor) {
const item = monitor.getItem();
const dropResult = monitor.getDropResult();
if (dropResult) {
console.log(`You dropped ${item.candidate_id} vers ${dropResult.status} !`);
$.post(`/update_status/${item.candidate_id}/${dropResult.status}`);
}
},
};
@DragSource(ItemTypes.CARD, cardSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
}))
export default class Card extends React.Component {
constructor(props, _railsContext) {
super(props);
}
render() {
const { isDragging, connectDragSource } = this.props;
const { name } = this.props;
const opacity = isDragging ? 0 : 1;
var candidate = this.props.candidate;
return (
connectDragSource(
<div className="card" key={candidate.id} style={{opacity}}>
<div className="content">
<div className="header">{`${candidate.first_name} ${candidate.last_name}`}</div>
<div className="description">
{candidate.job_title}
</div>
<span className="right floated">
<i className="heart outline like icon"></i>
{candidate.average_rate}
</span>
</div>
</div>
)
);
}
}
理解を深めるために、私の機能と彼のバグの gif をここに示します。