I have a top-level component that consists of a few different components.
InventoryBox - designates the space that an inventory contains
InventoryList - designates the list of items in the inventory
Item - a single item in the inventory list
InventoryBox is the top-level component, so I have wrapped it in a DragDropContext. The issue I am running into is that the connectDragSource function that I specified in my collect function is not injecting the method into my item components.
My Collect Function
function collect(connect, monitor) {
return {
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging()
};
}
My Item Component
var Item = React.createClass({
render: function(){
var id = this.props.id;
var isDragging = this.props.isDragging;
var connectDragSource = this.props.connectDragSource;
return (
<div className="item">
{this.props.children}
</div>
);
}
});
My ultimate goal would be to drag the Item components from the list to another Inventory Box.
When you are using Item in the Item inventoryList you are just using the Item not the wrapped one. var Item = React.... but you need to declare a variable.
var ItemWrapped = DragSource(Types.INVENTORY, itemSource, collect)(Item);
// Use the ItemWrapped instead.... the same goes for all
The DragSource returns this in the source
return function decorateSource(DecoratedComponent) {
return decorateHandler({
connectBackend: (backend, sourceId) => backend.connectDragSource(sourceId),
containerDisplayName: 'DragSource',
createHandler: createSource,
registerHandler: registerSource,
createMonitor: createSourceMonitor,
createConnector: createSourceConnector,
DecoratedComponent,
getType,
collect,
options
});
};
So you need to handle the returned function
Related
I am trying to call a function from a div like the following
<div id='div_abstract'>
{content.abstract && content.abstract.length ? (
<article id="abstract" onMouseUp={spanSelect}>{content.abstract </article>) : ''}
</div>
My functional component is structured like this
export default function ExternalInfos(props) {
...
function spanSelect() { ... }
return(
...
);
}
And the function I'm trying to call is
let table = [];
function spanSelect() {
var span = document.createElement("span");
span.setAttribute("id","span");
if (window.getSelection()) {
var text = window.getSelection();
if (text.rangeCount) {
var range = text.getRangeAt(0).cloneRange();
range.surroundContents(span);
text.removeAllRanges();
text.addRange(range);
};
};
let object = window.getSelection().toString();
table.push(object);
const annotation = document.getElementById("annotationArea");
annotation.updateObjectAnnotation(table);
}
But nothing happens when I select text from my div and it doesn't return an error.
How do I solve this?
You need to capitalize the event handler prop: onMouseUp.
From the React docs (https://reactjs.org/docs/handling-events.html):
"React events are named using camelCase, rather than lowercase."
I used the Selectable List, but if i wrote a custome listitem, the List isn't selectable. If I used listitem directly, the list is selectable.
var DataCenterRow = React.createClass({
render: function () {
return (
< ListItem primaryText = {this.props.datacenter.name}
rightIconButton= {rightIconMenu}
value={this.props.index} onTouchTap= {this.selectItem}/>
);
}
});
module.exports = DataCenterRow
If you look at the source code of makeSelectable, there is a check for muiName === 'ListItem', so make sure that your customized ListItem have type equals 'ListItem'.
ES6:
static muiName = 'ListItem';
ES5:
DataCenterRow.muiName = 'ListItem';
Don't forget to render DataCenterRow with the style got from outside (because makeSelectable will pass through selectedItemStyle to selected item)
We are working on a project with some challenging animation requirements.We are trying to do the animations in CSS and not get JS involved in the animation work. For example we have the following component (simplified for clarity):
var mainMenu = React.createClass({
mixins: [PureRenderMixin],
render: function () {
var _this = this;
var currItem;
var items = this.props.itemList.map(function (item) {
if (!item.get('isOpen')) {
currItem = <MainMenuClosed key={item.get('MenuItemId')}
menuTypeId={item.get('MenuTypeId')}
title={item.get('ItemTitle')}
text={item.get('ItemText')}
imageUrl={item.get('ImageId')}
clickHandler={_this.props.closedClickHandler} />;
} else {
currItem = <MainMenuOpen menuTypeId={item.get('MenuTypeId')}
key={item.get('MenuItemId')}
clickHandler={_this.props.openClickHandler}
items={item.get('children')}
/>;
}
return (
currItem
);
})
return (
<ReactCSSTransitionGroup component="div" className="row" transitionName="mainMenuItems">
{items}
</ReactCSSTransitionGroup>
);
}
});
When a menu item is clicked an action is called, which fetches some stuff from the server and sends it on to the stores. The problem is that once the re-render happens the leaving component fades out for example and the entering component fades in at the same time. I would like to let the leaving component finish its animation sequence and then have the entering menu item begin its animation. Is there a builtin way to create such a sequence?
I'm using an array of string categories to create input checkboxes. Checking the input box tells me you want to include that category and unchecking an input box tells me you don't want to include that category.
Problem is, I don't know what the ref of the object that is being clicked. How do I figure out the ref?
I'd like to pass this ref back up to my parent class so that it can find the index of the 'ref' in my array of categories, and splice that out. The result being that my filteredCategories array will remove the item when it is there and add it if it isn't
var HeaderCategories = React.createClass({
handleChange:function(e){
// I know what was clicked through e.target
// but I'd like to know the ref of what was clicked
// so that I can do somthing like the below:
this.props.filterTable(this.refs[e.target.ref])
},
render: function(){
var categories = this.props.allCategories.map(function(category){
return (
<label key={category}>{category}
<input type="checkbox" ref={category} onChange={this.handleChange}/>
</label>
)}.bind(this))
return (
<div className="categories __header" >{categories}</div>
);
}});
var Table = React.createClass({
allCategories: ["apples","oranges","bananas"]
componentDidMount:function(){
this.setState({filteredCategories:this.allCategories})
},
getInitialState:function(){
return {filteredCategories:this.allCategories}
},
filterTable:function(category){
// If I have the ref then I can use a splice and remove it from my filtered Categories
//this is pseudo code, havent checked if it works
var index = filteredCategories.indexOf(category)
var filteredCategories.splice(index,filteredCategories.length)
this.setState(filteredCategories:filteredCategories)
},
render:function(){
return <Header filterTable={this.filterTable} allCategories={this.allCategories}>
}
})
There is not a good way to get a reference to a component from the event param of the onClick callback. You best option is to curry either the category index or name to the callback like this (in this example, I'm passing back just the index)
handleChange:function(e, categoryIndex){
// `categoryIndex` was curried in the click handler
// of each checkbox in the render function below so
// the filterTable callback should accept the index.
this.props.filterTable(categoryIndex);
},
render: function(){
var categories = this.props.allCategories.map(function(category, index){
return (
<label key={category}>{category}
<input type="checkbox" ref={category} onChange={this.handleChange.bind(this, index)}/>
</label>
)}, this); // map's second param is thisArg
return (
<div className="categories __header" >{categories}</div>
);
I'm just getting started with React. I have a project that includes many tables, some pretty complex, but all generally output a table from a set of data. Some have parent-child relationships (with toggleable child rows), and each has a slightly different format for the row output (e.g. some have buttons that open modals). Normally, I would use jQuery DataTables for this, which is easy and flexible for something like this. I'm struggling to figure out how to do it sustainably (scaleably?) in React, though.
I've written a basic table component where it accepts a set of items via props and spits out a table and handles child rows via internal state. Today I'll convert that to use two components: the table and a separate one for the rows. I really don't want to have to write X or 2X different components though (where X is the number of tables in the project), but I'm not sure how to make it reusable. All of the tables should have some things in common like style, filter capability, paging, etc., which I would try to put at the Table component level and reuse.
The best solution so far that I've thought about doing is passing in a preRender function via props and using that to create the actual row JSX, and having the render function just assemble all of those snippets into one output (which is basically what I do already but with Array.map. I could then provide the preRender via a prop (if that works), like this:
var Table = React.createClass({
render: function() { // mixin?
var rows = [];
for (var i=0; i<this.props.items.length; i++) {
rows.push(this.props.preRender(this.props.items[i]));
}
return rows; // plus html boilerplate...
}
});
var Parent = React.createClass({
render: function() {
var foodItems = this.state.foodItems;
var drinkItems = this.state.drinkItems;
var foodRender = function(i) { return (<tr>{i} <a href?>Buy me</a></tr>); }
var drinkRender = function(i) { return (<tr>{i} <button>Drink me</button></tr>); }
return (
<Table items={foodItems} preRender={foodRender}/>
<Table items={drinkItems} preRender={drinkRender}/>
);
}
});
Another thing I thought of was somehow passing in a different Row component to the Table component, if that's possible. I guess the root problems are:
The table-level stuff is very similar or identical across tables but may have parts needing customization per-table.
The rows do things like open popovers, so they will have a state (or need to circle around w/props).
Is there a better way to do this sort of logic/dependency injection, or will I probably just need to make a ton of slightly-different controls.
I'd start with something like this (using ES6 syntax for brevity):
const FoodItem = React.createClass({
render() {
return (
<tr><td>{this.props.item} Buy me</td></tr>
);
}
});
const DrinkItem = React.createClass({
render() {
return (
<tr><td>{this.props.item} <button>Drink me</button></td></tr>
);
}
});
const Table = React.createClass({
render() {
const {items, itemComponent: ItemComponent} = this.props;
return (
<table>
{items.map(item => <ItemComponent item={item} />)}
</table>
);
}
});
const Parent = React.createClass({
render() {
return (
<div>
<Table items={this.state.foodItems} itemComponent={FoodItem}/>
<Table items={this.state.drinkItems} itemComponent={DrinkItem}/>
</div>
);
}
});
An alternative pattern would be this (which is best depends on your requirements):
const FoodItem = React.createClass({
render() {
return (
<tr><td>{this.props.item} Buy me</td></tr>
);
}
});
const DrinkItem = React.createClass({
render() {
return (
<tr><td>{this.props.item} <button>Drink me</button></td></tr>
);
}
});
const Table = React.createClass({
render() {
// I'm assuming you ultimately want your table to do something cleverer than just rendering a table element
return (
<table>{this.props.children}</table>
);
}
});
const Parent = React.createClass({
render() {
return (
<div>
<Table>{this.state.foodItems.map(item => <FoodItem item={item} />)}</Table>
<Table>{this.state.drinkItems.map(item => <DrinkItem item={item} />)}</Table>
</div>
);
}
});