Trying to sort data inside a react table: Reactjs - javascript

I am trying to sort the table data based on the field selected from the dropdown. It should alternatively sort between ascending or descending whenever the same field is clicked. I am maintaining a sort object that decides which field is selected and what is the sort order. Then it is sent to lodash orderBy with the field and the order. It does not work
This is what I have tried. Can some one tell me what I am doing wrong. Help is really appreciated.
https://codesandbox.io/s/simple-react-class-component-1n3f9?file=/src/index.js:0-3000
import React from "react";
import ReactDOM from "react-dom";
import "semantic-ui-css/semantic.min.css";
import { Dropdown } from "semantic-ui-react";
import moment from "moment";
import orderby from "lodash.orderby";
const options = [
{ key: 1, text: "Name", value: "name", icon: "sort" },
{ key: 2, text: "Time", value: "time", icon: "sort" },
{ key: 3, text: "Type", value: "type", icon: "sort" }
];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [],
original: [],
sortObject: { field: "", order: "" }
};
}
componentDidMount() {
let list = [
{
name: "namev1",
time: 1583295463213,
type: 14
},
{
name: "namea2",
time: 1582885423296,
type: 15
},
{
name: "namea3",
time: 1581295463213,
type: 16
}
];
this.setState({ list, original: list });
}
handleSearch = e => {
let searchInput = e.target.value;
let filteredData = this.state.original.filter(value => {
return (
value.name.toLowerCase().includes(searchInput.toLowerCase()) ||
value.type.toString().includes(searchInput.toString())
);
});
this.setState({ list: filteredData });
};
formSortObject = fieldName => {
let { sortObject } = this.state;
if (!sortObject.field || sortObject.field !== fieldName) {
Object.assign(sortObject, {
field: fieldName,
order: "asc"
});
return sortObject;
} else if (sortObject.field === fieldName) {
Object.assign(sortObject, {
...sortObject,
order: sortObject.order === "desc" ? "asc" : "desc"
});
return sortObject;
}
};
handleSort = (e, data) => {
let dropdDownValue = data.value;
let currentField = this.formSortObject(dropdDownValue);
let result = orderby(
this.state.list,
currentField.field,
currentField.order
);
this.setState({ list: result });
};
render() {
return (
<>
Search: <input type="text" onChange={this.handleSearch} />
<Dropdown text="Sort By" options={options} onChange={this.handleSort} />
<h1>List</h1>
<table>
<tbody>
{this.state.list.map((item, index) => (
<tr key={index}>
<td>
<p>{index + 1}</p>
</td>
<td>
<p>{item.name}</p>
</td>
<td>
<p>{moment().diff(item.time, "days")}</p>
</td>
<td>
<p>{item.type}</p>
</td>
</tr>
))}
</tbody>
</table>
</>
);
}
}

Your code isnt's working as you spected because you are calling the handleSort function only when the value of the select change (see the onChange of your <Dropdown />).
What you need is the function executed when an option is clicked.
I searched for the documentation of the library you are using and I came to the conclusion that what you need is this.
<Dropdown text='Sort By'>
<Dropdown.Menu>
{options.map(item=>
<Dropdown.Item text={item.text} value={item.value} icon={item.icon} key={item.key} onClick={this.handleSort}/>
)}
</Dropdown.Menu>
</Dropdown>
I tried it in your codesandbox and it works perfectly!
I hope it helps!

Related

How to manage props of a list of components in React?

I am trying to create an ObjectList component, which would contain a list of Children.
const MyList = ({childObjects}) => {
[objects, setObjects] = useState(childObjects)
...
return (
<div>
{childObjects.map((obj, idx) => (
<ListChild
obj={obj}
key={idx}
collapsed={false}
/>
))}
</div>
)
}
export default MyList
Each Child has a collapsed property, which toggles its visibility. I am trying to have a Collapse All button on a parent level which will toggle the collapsed property of all of its children. However, it must only change their prop once, without binding them all to the same state. I was thinking of having a list of refs, one for each child and to enumerate over it, but not sure if it is a sound idea from design perspective.
How can I reference a dynamic list of child components and manage their state?
Alternatively, is there a better approach to my problem?
I am new to react, probably there is a better way, but the code below does what you explained, I used only 1 state to control all the objects and another state to control if all are collapsed.
Index.jsx
import MyList from "./MyList";
function Index() {
const objList = [
{ data: "Obj 1", id: 1, collapsed: false },
{ data: "Obj 2", id: 2, collapsed: false },
{ data: "Obj 3", id: 3, collapsed: false },
{ data: "Obj 4", id: 4, collapsed: false },
{ data: "Obj 5", id: 5, collapsed: false },
{ data: "Obj 6", id: 6, collapsed: false },
];
return <MyList childObjects={objList}></MyList>;
}
export default Index;
MyList.jsx
import { useState } from "react";
import ListChild from "./ListChild";
const MyList = ({ childObjects }) => {
const [objects, setObjects] = useState(childObjects);
const [allCollapsed, setallCollapsed] = useState(false);
const handleCollapseAll = () => {
allCollapsed = !allCollapsed;
for (const obj of objects) {
obj.collapsed = allCollapsed;
}
setallCollapsed(allCollapsed);
setObjects([...objects]);
};
return (
<div>
<button onClick={handleCollapseAll}>Collapse All</button>
<br />
<br />
{objects.map((obj) => {
return (
<ListChild
obj={obj.data}
id={obj.id}
key={obj.id}
collapsed={obj.collapsed}
state={objects}
setState={setObjects}
/>
);
})}
</div>
);
};
export default MyList;
ListChild.jsx
function ListChild(props) {
const { obj, id, collapsed, state, setState } = props;
const handleCollapse = (id) => {
console.log("ID", id);
for (const obj of state) {
if (obj.id == id) {
obj.collapsed = !obj.collapsed;
}
}
setState([...state]);
};
return (
<div>
{obj} {collapsed ? "COLLAPSED!" : ""}
<button
onClick={() => {
handleCollapse(id);
}}
>
Collapse This
</button>
</div>
);
}
export default ListChild;

Unable to access the table header data

I'm developing an app using React. However, facing some issue with reflecting the {column.label} at column header field. The code works with any plain text but not for inputs in {}.
Below is the code for reference.
filename: tableHeader.jsx:
import React, { Component } from "react";
class TableHeader extends Component {
raiseSort = (path) => {
const sortColumn = { ...this.props.sortColumn };
if (sortColumn.path === path)
sortColumn.order = sortColumn.order === "asc" ? "desc" : "asc";
else {
sortColumn.path = path;
sortColumn.order = "asc";
}
this.props.onSort(sortColumn);
};
render() {
return (
<thead>
<tr>
{this.props.columns.map((column) => (
<th
key={column.path || column.key}
onClick={() => this.raiseSort(column.path)}
>
{column.label}
</th>
))}
</tr>
</thead>
);
}
}
export default TableHeader;
filename: moviesTable.jsx:
import React, { Component } from "react";
import Like from "./common/like";
import TableHeader from "./common/tableHeader";
class MoviesTable extends Component {
columns = [
{ path: "title", lable: "Title" },
{ path: "genre.name", lable: "Genre" },
{ path: "numberInStuck", lable: "Stock" },
{ path: "dailyRentalRate", lable: "Rate" },
{ key: "Like" },
{ key: "Delete" },
];
render() {
const { movies, onDelete, onLike, onSort, sortColumn } = this.props;
return (
<table className="table">
<TableHeader
columns={this.columns}
sortColumn={sortColumn}
onSort={onSort}
/>
<tbody>
{movies.map((movie) => (
<tr key={movie._id}>
<td> {movie.title} </td>
<td> {movie.genre.name} </td>
<td> {movie.numberInStock} </td>
<td> {movie.dailyRentalRate} </td>
<td>
<Like liked={movie.liked} onClick={() => onLike(movie)} />
</td>
<td>
<button
onClick={() => onDelete(movie)}
className="btn btn-danger btn-sm"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
);
}
}
export default MoviesTable;
fileName: movie.jsx:
import React, { Component } from "react";
import { getMovies } from "../services/fakeMovieService";
import { getGenres } from "../services/fakeGenreService";
import Pagination from "./common/pagination";
import { paginate } from "../utils/paginate";
import ListGorup from "./common/listGroup";
import MoviesTable from "./moviesTable";
import _ from "lodash";
class Movies extends Component {
state = {
movies: [],
genres: [],
pageSize: 4,
currentPage: 1,
sortColumn: { path: "title", order: "asc" },
};
componentDidMount() {
const genres = [{ _id: "", name: "All Genres" }, ...getGenres()];
this.setState({ movies: getMovies(), genres });
}
handleDelete = (movie) => {
const movies = this.state.movies.filter((m) => m._id !== movie._id);
this.setState({ movies });
};
handleLike = (movie) => {
const movies = [...this.state.movies];
const index = movies.indexOf(movie);
movies[index] = { ...movie };
movies[index].liked = !movies[index].liked;
this.setState({ movies });
};
handlePageChange = (page) => {
this.setState({ currentPage: page });
};
handleGenreSelect = (genre) => {
this.setState({ selectedGenre: genre, currentPage: 1 });
};
handleSort = (sortColumn) => {
this.setState({ sortColumn });
};
render() {
const { length: count } = this.state.movies;
const {
pageSize,
currentPage,
movies: allMovies,
selectedGenre,
sortColumn,
} = this.state;
if (count === 0) return <p>No movies in the DB..</p>;
const filtered =
selectedGenre && selectedGenre._id
? allMovies.filter((m) => m.genre._id === selectedGenre._id)
: allMovies;
const sorted = _.orderBy(filtered, [sortColumn.path], [sortColumn.order]);
const movies = paginate(sorted, currentPage, pageSize);
return (
<div>
<div className="row">
<div className="col-3">
<ListGorup
items={this.state.genres}
onItemSelect={this.handleGenreSelect}
selectedItem={this.state.selectedGenre}
/>
</div>
<div className="col">
<p>Showing {filtered.length} movies in the DB. </p>
<MoviesTable
movies={movies}
onLike={this.handleLike}
onDelete={this.handleDelete}
onSort={this.handleSort}
sortColumn={sortColumn}
/>
<Pagination
itemsCount={filtered.length}
onPageChange={this.handlePageChange}
pageSize={pageSize}
currentPage={currentPage}
/>
</div>
</div>
</div>
);
}
}
export default Movies;
The below code from file1(tableHeader.jsx) is responsible to give the column name. Not sure, why it's not coming.
<thead>
<tr>
{this.props.columns.map((column) => (
<th
key={column.path || column.key}
onClick={() => this.raiseSort(column.path)}
>
{column.label}
</th>
))}
</tr>
</thead>
Looking for to hearing from you.
Your columns list only contains objects with the key lable (misspelled). It should be label:
columns = [
{ path: "title", /* not lable ! */ label: "Title" },
{ path: "genre.name", label: "Genre" },
{ path: "numberInStuck", label: "Stock" },
{ path: "dailyRentalRate", label: "Rate" },
{ key: "Like" },
{ key: "Delete" },
];

Displaying/Hiding array items based on condition : ReactJS

I have got a grid where in a column can have array of items. All I need is to implement a solution where in If that column has more than 1 items, need to display "Show more" and on click of it should show all the items(comma separated) and bring a "Show Less " link that would hide all items except the first one .Also when there is no data , just show "Not Available" for that column value. I am using react-table for grid purposes
I have tried the following : https://codesandbox.io/s/react-table-row-table-mpk9s
import * as React from "react";
import { render } from "react-dom";
import DataGrid from "./DataGrid";
import ShowMore from "./ShowMore";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
columns: [],
};
}
componentDidMount() {
this.getData();
this.getColumns();
}
showMoreUtility = arr => {
return <ShowMore value={arr} />;
};
getData = () => {
const data = [
{ firstName: "Jack", status: "Submitted", items: [1, 2, 3, 4] },
{ firstName: "Simon", status: "Pending", items: [1, 2] },
{ firstName: "Syls", status: "Pending", items: [1, 2] },
{ firstName: "Pete", status: "Approved", items: [] }
];
this.setState({ data });
};
getColumns = () => {
const columns = [
{
id: "1",
Header: "First Name",
accessor: "firstName"
},
{
id: "2",
Header: "Status",
accessor: "status"
},
{
id: "3",
Header: "Items",
accessor: arr => this.showMoreUtility(arr.items)
}
];
this.setState({ columns });
};
render() {
return (
<>
<DataGrid
data={this.state.data}
columns={this.state.columns}
/>
</>
);
}
}
Based on the code from the linked sandbox you could add a Cell property to the items column and pass the value to your ShowMore component:
{
Header: "Items",
accessor: "items",
Cell: row => (
<ShowMore value={row.value} />
)
}
then in your ShowMore component add || !value.length to your condition in order to return Not Available when there is no data
if (value === undefined || value === null || !value.length) {
return 'Not Available';
}
Also add a onClick event to the div to update the value of isTruncated and change the displayed data:
function handleClick() {
truncate(!isTruncated);
}
return (
<div onClick={handleClick}>
{
isTruncated
? <span>
{value[0]}
{value.length > 1 && ' Show more'}
</span>
: <span>
{value.join(',')}
{value.length > 1 && ' Show less'}
</span>
}
</div>
);
Working example:
You're almost there. The ShowMore component needs some modifications and the items column isn't correct either.
I wrote an example of a working ShowMore component to display how this can be done:
const ShowMore = props => {
const { value } = props;
const [isTruncated, setTruncate] = useState(true);
const toggleTruncate = () => setTruncate(!isTruncated);
if (value === undefined || value === null) {
return null;
}
if (value.length === 0) {
return 'Unavailable'
}
return (
<div>
{isTruncated ? value[0] : value}
<span onClick={toggleTruncate}>
{isTruncated ? "Show more" : "Show less"}
</span>
</div>
);
};
When modifying the ShowMoreItem component like this it will work, but according to the specs of react-table this isn't the correct way to use it. The accessor attribute should be used to retrieve the correct data instead of rendering a custom component. For custom rendering you can use the Cell attribute.
Modify the items columns like following:
accessor: "items", // This will get the 'items' attribute from the row.
Cell: row => {
// This will render the ShowMore component with the correct value.
return <ShowMore value={row.value} />;
}

Need to get all the values of all the child component instances and use it in parents method: ReactJS

I have this scenario where I have a table(react-table), where I am applying column level filtering. I have extracted this as a separate component(DropdDown Component) and this can be attached to any column . I am maintaining a method inside parent component which picks up the union of all the values i.e., selected values of all the dropdowns and then apply server side filtering.
Now the challenge here is , How can i get this consolidated values inside the parent component method?
This DropDown component has list of unique values with respect to that column, there is an Apply button , which applies the server side filtering. Now if I jump onto another column, I need to get the previously checked values and also the current values.
Inside handleSetData() filtering logic is written, I need to get the data from DropDown Component. Everytime I click on Apply on a column filter, I need to get the previously checked values as well.
Can someone help me with this:
Code Sandbox: https://codesandbox.io/s/quizzical-glitter-np8iw
App Component
import * as React from "react";
import { render } from "react-dom";
import ReactTable from "react-table";
import "./styles.css";
import "react-table/react-table.css";
import DropDownComponent from "./DropDown";
interface IState {
data: {}[];
columns: {}[];
}
interface IProps {}
export default class App extends React.Component<IProps, IState> {
constructor(props: any) {
super(props);
this.state = {
data: [
{ firstName: "aaaaa", status: "Pending", visits: 155 },
{ firstName: "aabFaa", status: "Pending", visits: 155 },
{ firstName: "adaAAaaa", status: "Approved", visits: 1785 },
{ firstName: "aAaaaa", status: "Approved", visits: 175 },
{ firstName: "adaSaaa", status: "Cancelled", visits: 165 },
{ firstName: "aaaaa", status: "Cancelled", visits: 157 },
{ firstName: "aaaaa", status: "Approved", visits: 153 },
{ firstName: "aaaaa", status: "Pending", visits: 155 }
],
columns: []
};
}
handleSetState = (columns: any) => {
this.setState({ columns });
};
handleSetData = (value: any) => {
console.log(value); // Here filtering logic is written, I need to get the data from DropDown Component. Everytime I click on Apply on a column filter, I need to get the previously checked values as well
};
componentDidMount() {
let columns = [
{
Header: () => (
<div>
<div style={{ position: "absolute", marginLeft: "10px" }}>
<DropDownComponent
data={this.state.data}
handleSetData={this.handleSetData}
param="firstName"
/>
</div>
<span>First Name</span>
</div>
),
accessor: "firstName",
sortable: false,
show: true,
displayValue: " First Name"
},
{
Header: () => (
<div>
<div style={{ position: "absolute", marginLeft: "10px" }}>
<DropDownComponent
data={this.state.data}
handleSetData={this.handleSetData}
param="status"
/>
</div>
<span>Status</span>
</div>
),
accessor: "status",
sortable: false,
show: true,
displayValue: " Status "
},
{
Header: "Visits",
accessor: "visits",
sortable: false,
show: true,
displayValue: " Visits "
}
];
this.setState({ columns });
}
render() {
const { data, columns } = this.state;
return (
<div>
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className="-striped -highlight"
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
DropDown Component
import * as React from "react";
import { Button, Checkbox, Icon } from "semantic-ui-react";
interface IProps {
data: {}[];
handleSetData(arr: any): void;
param: string;
}
interface IState {
showList: boolean;
optionsArr: {}[];
originalState: {}[];
}
export default class DropDownComponent extends React.Component<IProps, IState> {
constructor(props: any) {
super(props);
this.state = {
showList: false,
optionsArr: [],
originalState: []
};
}
toggleList = () => {
this.setState(prevState => ({ showList: !prevState.showList }));
};
handleItemClick = (event: React.FormEvent<HTMLInputElement>, data: any) => {
const index = this.state.optionsArr.findIndex(
(item: any) => item.text === data.name
);
const optionsArr = this.state.optionsArr.map((prevState: any, i: any) =>
i === index
? {
key: prevState.key,
text: prevState.text,
checked: !prevState.checked
}
: prevState
);
this.setState({ optionsArr });
};
submitSelection = () => {
console.log(this.state.optionsArr.filter((item: any) => item.checked)); // This gives me selecte ones
let checkedValues: any = this.state.optionsArr.filter(
(item: any) => item.checked
);
this.setState({ originalState: this.state.optionsArr }, () =>
this.props.handleSetData(checkedValues)
);
};
componentDidMount() {
if (this.props.data) {
let arr = this.props.data;
let uniqueValues = Array.from(
new Set(arr.map((arr: any) => arr[this.props.param]))
);
var optionsArr = [];
for (let i = 0; i < uniqueValues.length; i++) {
var options: any = {};
options["key"] = uniqueValues[i];
options["text"] = uniqueValues[i];
options["checked"] = false;
optionsArr.push(options);
}
this.setState({ optionsArr: optionsArr, originalState: optionsArr });
}
}
clearSelection = (event: any) => {
// Push it to previous state, before cancel was clicked
this.setState({ showList: false, optionsArr: this.state.originalState });
};
render() {
let { showList } = this.state;
let visibleFlag: string;
if (showList === true) visibleFlag = "visible";
else visibleFlag = "";
return (
<div>
<div style={{ position: "absolute" }}>
<div
className={
"ui scrolling dropdown column-settings customized " +
visibleFlag +
" " +
this.props.menuDirection
}
>
<Icon className="filter" onClick={this.toggleList} />
{this.state.optionsArr.length > 0 ? (
<>
<div className="menu-item-holder">
{this.state.optionsArr.map((item: any, i: number) => (
<div className="menu-item" key={i}>
<Checkbox
name={item.text}
onChange={this.handleItemClick}
checked={item.checked}
label={item.text}
/>
</div>
))}
</div>
<div className="menu-btn-holder">
<Button size="small" onClick={this.submitSelection}>
Apply
</Button>
<Button size="small" onClick={this.clearSelection}>
Cancel
</Button>
</div>
</>
) : (
""
)}
</div>
</div>
</div>
</div>
);
}
}
I have modified your DropDown component. I make it receive a list of items to generate the checkboxes. Instead of sending the whole data object to the DropDown component, I think it makes more sense send a ready list to them, the Main component should generate the right data structure (I haven't done that, you have to create those functions). In the component, I create three states to manage the component.
Obs: I removed typescript to make faster for me.
condesandbox

React Complex Form Editing key value pair

I am building a form to edit a key/value pair object, see picture:
This is the object that I get from the backend that I stored in the container component.
items: [{
name: "Product Name",
sku: "00001",
attributes: {
width: "value",
height: "value",
length: "value",
color: "value"
}
},
{
name: "Product Name 2",
sku: "00002",
attributes: {
description: "Hello World",
weight: "250",
quantity: "500",
hello: "World"
}
}]
I then pass the data into a child component via props. This is the code for the form:
class EditForm extends Component {
render() {
let editForm = this.props.items && this.props.items.map((item, idx) => {
return(
<tr key={item.sku}>
<td className="edit-table">
<input
value={item.name}
name={item.name}
onChange={(e)=> this.props.onChange(e, idx)}
/>
</td>
<td className="edit-table">
<ul className="item-attributes">
{Object.keys(item.attributes).map((key) => {
return (<li key={key}>
<label>{key}</label>
<input
value={item.attributes[key]}
onChange={(e) => this.props.onChange(e, idx) }
/>
</li>)
})}
</ul>
</td>
</tr>
)
})
return(
<table className="editcontainer-table">
<thead>
<tr>
<th>SKU</th>
<th>Attributes</th>
</tr>
</thead>
<tbody>
{editForm}
</tbody>
</table>
);
}
}
Now, this is where I'm stuck, I'm trying to figure out how the onChange function would work for me to edit the objects in the state and send back to the server for updating.
Give the item name input a name="name" attribute
Give the attribute inputs names per the attribute: name={key}
You can now identify what's being edited in onChange - make the appropriate state change based on the index and input name being changed.
e.g. (using import update from 'immutability-helper') onChange might look like this:
onChange = (e, index) => {
let {name, value} = e.target
let updateSpec
if (name === 'name') {
updateSpec = {
[index]: {
name: {$set: value}
}
}
}
else {
updateSpec = {
[index]: {
attributes: {
[name]: {$set: value}
}
}
}
}
this.setState({items: update(this.state.items, updateSpec)})
}
Here's an example app which shows this solution in action:
Live version
Full example source
I would change the onChange function in your Container to be the following:
onChange = (e, sku, field) => {
const updatedItems = this.state.items.map(e => {
if (e.sku !== sku) return e;
if (field === 'name') {
e.name = e.target.value;
} else {
// has to be attributes
e.attributes[field] = e.target.value;
}
return e;
});
this.setState({
items: updatedItems,
})
}
Added sku parameter to identify the item in items array and the field you want to change. Since sku is not going to change, we can use this as the item identifier. This way, you can change the product name and its respective attributes. For full working code, see the code example below.
class Container extends React.Component {
constructor() {
super();
this.state = {
items: [{
name: "Product Name",
sku: "00001",
attributes: {
width: "value",
height: "value",
length: "value",
color: "value"
}
},
{
name: "Product Name 2",
sku: "00002",
attributes: {
description: "Hello World",
weight: "250",
quantity: "500",
hello: "World"
}
}],
}
}
onChange = (e, sku, field) => {
console.log(e.target.value);
const updatedItems = this.state.items.map(item => {
if (item.sku !== sku) return item;
if (field === 'name') {
item.name = e.target.value;
} else {
// has to be attributes
item.attributes[field] = e.target.value;
}
return item;
});
this.setState({
items: updatedItems,
})
}
render() {
// log new state here
console.log(this.state.items);
return <EditForm onChange={this.onChange} items={this.state.items} />
}
}
class EditForm extends React.Component {
render() {
let editForm = this.props.items && this.props.items.map((item, idx) => {
return(
<tr key={item.sku}>
<td className="edit-table">
<input
value={item.name}
name={item.name}
onChange={(e)=> this.props.onChange(e, item.sku, 'name')}
/>
</td>
<td className="edit-table">
<ul className="item-attributes">
{Object.keys(item.attributes).map((key) => {
return (<li key={key}>
<label>{key}</label>
<input
value={item.attributes[key]}
onChange={(e) => this.props.onChange(e, item.sku, key) }
/>
</li>)
})}
</ul>
</td>
</tr>
)
})
return(
<table className="editcontainer-table">
<thead>
<tr>
<th>SKU</th>
<th>Attributes</th>
</tr>
</thead>
<tbody>
{editForm}
</tbody>
</table>
);
}
}
ReactDOM.render(<Container />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Categories

Resources