I want the states of my textinput to be dispatched to the reducer and change the state of of that reducer by the new state. I also want to be able to view these changed states in a new screen (globally) using mapStateToProps. I am roughly new to redux and I have tried everything possible, but I can seem to get it to work.
Is there any way to do that? I researched and found examples but not the way I want to do it.
I clarify my code is just an example so that you understand what I want to do, do not take it as a guide as I do not know if it works that way
Below are the important part of my code:
Process.Js
import { connect } from 'react-redux';
import {
receiverNameChange,
receiverPhoneChange,
totalParcelsChange } from './actions';
class Process extends Component {
static navigationOptions = {
header: null,
}
constructor(props) {
super(props);
this.state = {
totalParcels: 1,
receiverPhone: '',
receiverName: '',
};
}
onChangeTotalParcels(number) {
const totalParcels = parseInt(number);
if (number.length === 0) {
this.setState({ totalParcels: '' });
} else {
this.setState({ totalParcels });
}
this.props.totalParcelsChange(number);
}
onChangeReceiverNumber = (receiverPhone) => {
this.setState({
receiverPhone
});
this.props.receiverPhoneChange(receiverPhone);
}
onChangeReceiverName = (receiverName) => {
this.setState({
receiverName
});
this.props.receiverNameChange(receiverName);
}
render() {
return (
<View style={styles.AndroidSafeArea}>
<InputField
placeholder={"Enter receiver's name"}
onChangeText={this.onChangeReceiverName}
value={this.state.receiverName}
/>
<InputField
keyboardType={'phone-pad'}
onChangeText={this.onChangeReceiverNumber}
value={this.state.receiverPhone.toString()}
/>
<InputField
keyboardType={'phone-pad'}
onChangeText={this.onChangeTotalParcels}
value={this.state.totalParcels.toString()}
/>
</View>
);
}
}
const mapDispatchToProps = (dispatch) => ({
totalParcelsChange: number => {
dispatch(totalParcelsChange(number));
},
receiverNameChange: receiverName => {
dispatch(receiverNameChange(receiverName));
},
receiverPhoneChange: receiverPhone => {
dispatch(receiverPhoneChange(receiverPhone));
},
});
export default connect(null, mapDispatchToProps)(Process);
Receive.js
import { connect } from 'react-redux';
import {
receiverNameChange,
receiverPhoneChange,
totalParcelsChange } from './actions';
class Receive extends Component {
static navigationOptions = {
header: null,
}
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<View style={styles.AndroidSafeArea}>
<Text>{this.props.receiverNameChange}</Text>
<Text>{this.props.receiverPhoneChange}</Text>
<Text>{this.props.totalParcelsChange}</Text>
</View>
);
}
}
export default connect(null, null)(Receive);
Reduce.js
import { GET_TOTAL_PARCELS, GET_RECEIVER_NAME, GET_RECEIVER_PHONE } from './actions/types';
const initialState = {
receiverName: '',
receiverPhone: '',
number: 0,
};
const ProcessReducer = (state = initialState, action) => {
switch (action.type) {
case GET_TOTAL_PARCELS:
return {
...state,
number: action.payload
};
case GET_RECEIVER_PHONE:
return {
...state,
receiverPhone: action.payload
};
case GET_RECEIVER_NAME:
return {
...state,
receiverName: action.payload
};
default:
return state;
}
};
export default ProcessReducer;
Actions
import { GET_RECEIVER_NAME, GET_RECEIVER_PHONE, GET_TOTAL_PARCELS } from './types';
export const receiverNameChange = (receiverName) => {
return {
type: GET_RECEIVER_NAME,
payload: receiverName
};
};
export const receiverPhoneChange = (receiverPhone) => {
return {
type: GET_RECEIVER_PHONE,
payload: receiverPhone
};
};
export const totalParcelsChange = (number) => {
return {
type: GET_TOTAL_PARCELS,
payload: number
};
};
Kindly correct me where necessary.
I in order for your component in Receive.js to access the state from redux, you should have a mapStateToProps, use it like so:
class Receive extends Component {
...
render() {
return (
<View style={styles.AndroidSafeArea}>
<Text>{this.props.receiverName}</Text>
<Text>{this.props.receiverPhone}</Text>
<Text>{this.props.number}</Text>
</View>
);
}
}
}
const mapStateToProps = state => {
return {
receiverName: state.receiverName,
receiverPhone: state.receiverPhone,
number: state.number
}
}
export default connect(mapStateToProps, null)(Receive);
To have a single source of truth in your Process.Js, you should remove the local state in your Process component and replace the values same as we did in Receive component and you can remove setState.
Hope this helps your problem.
Related
Hi Im fairly new to coding. I am using react redux and created a store, reducers etc. I cant get anything to render to the screen and when I console.log this.props it comes up an empty array. The data Im dealing with is an array of objects I set the initialstate to an array of objects. I connected all the components with connect and mapstateto props function, there is an empty object in the first arguement of the connect and the second arguement is the componenet. When I look at my component tree it looks fine but my state is undefined and cant figure out why? Here is my code. Thank you in advance.
export const FETCH_SMURFS_START ="FETCH__SMURFS_START"
export const FETCH_SMURFS_SUCCESS = "FETCH_SMURFS_SUCCESS"
export const FETCH_SMURFS_FAILURE ="FETCH_SMURFS_FAILURE"
export const ADD_SMURF_START = "ADD_SMURF_START"
export const ADD_SMURF_SUCCESS = "ADD_SMURF_SUCCESS"
export const ADD_SMURF_FAILURE = "ADD_SMURF_FAILURE"
export const getSmurfData = () =>dispatch=>{
dispatch({type:FETCH_SMURFS_START})
console.log(FETCH_SMURFS_START)
axios.get(' http://localhost:3333/smurfs')
.then((res)=>{
console.log(res.data)
dispatch({type:FETCH_SMURFS_SUCCESS, payload:res.datay})
})
.catch((err)=> {
dispatch({type:FETCH_SMURFS_FAILURE, payload:err.message})
})
}
export const putSmurfData = () =>dispatch=>{
dispatch({type:ADD_SMURF_START})
console.log(ADD_SMURF_START)
dispatch({ADD_SMURF_SUCCESS})
axios.put(' http://localhost:3333/smurfs')
.then((res)=>{
dispatch({type:ADD_SMURF_SUCCESS, payload:res.data})
})
.catch((err)=> {
dispatch({type:ADD_SMURF_FAILURE, payload:err.message})
})
}
class SmurfDisplay extends React.Component {
componentDidMount() {
getSmurfData();
}
render() {
return (
<>
<div>
{this.props.newSmurfData.map((smurf, index) => (
<div>
<h4 key={smurf.id}></h4>
<p> {index}</p>
<p>{smurf.description}</p>
<p>{smurf.nickname}</p>
<p>{smurf.name}</p>
<p>{smurf.position}</p>
</div>
))}
</div>
</>
);
}
}
const mapStateToProps = (state) => {
return {
newSmurfData: [
{
error:state.error,
id: state.id,
name: state.name,
position: state.position,
nickname: state.nickname,
description: state.description,
},
],
};
};
export default connect(mapStateToProps, {})(SmurfDisplay);
class Smurf extends React.Component {
render() {
console.log(this.props);
return (
<>
{this.props.smurfData.map(function(smurf,index) {
return(
<div>
<h4 key={index}></h4>
<p>{smurf.description}</p>
<p>{smurf.nickname}</p>
<p>{smurf.name}</p>
<p>{smurf.position}</p>
</div>
)
})}
</>
)
}
}
const mapStateToProps = (state) =>{
return{
smurfData:[{
error:state.error,
id:state.id,
name:state.name,
position:state.position,
nickname:state.nickname,
description:state.description
}]
}
}
export default connect(mapStateToProps,{})(Smurf)
xport const initialState = {
error:"",
isLoading: false,
smurfData : [{
id:"",
name:"",
position:"",
nickname:"",
description:""
}],
error:"",
isAddingSmurf:false,
newSmurfData:[{
id:"",
name:"",
position:"",
nickname:"",
description:""
}],
}
export const reducer = (state = initialState,action) =>{
switch(action.type){
case FETCH_SMURFS_START:
return{
...state,
isLoading:true,
error:""
}
case FETCH_SMURFS_SUCCESS:
return{
...state,
isLoading:false,
smurfData:action.payload
}
case FETCH_SMURFS_FAILURE:
return{
...state,
isLoading:false,
error:"there was an error getting your smurfs"
}
case ADD_SMURF_START:
return{
...state,
isAddingSmurf:false,
error:""
}
case ADD_SMURF_SUCCESS:
return{
...state,
isAddingSmurf:true,
error: "",
newSmurfData:action.payload
}
case ADD_SMURF_FAILURE:
return{
...state,
isAddingSmurf:false,
addingError:"Error"
}
default:
return state
}
}
export default reducer;
when you want to use this.props in your class Component you need to use super(props) inside the constructor:
constructor(props){
super(props)
}
I am trying to create a sort button which when clicked will sort me menu cards alphabetically. My question is how should I have the sort function coded in the Reducer and Actions? I added pseudo-code for sorting in the Reducer as well. When I click the button I am getting "(TypeError): state.slice is not a function".
Edit:
Added my button component and main Container.
Actions:
export const sortMenus = () => {
return dispatch => {
dispatch({ type: "LOADING_MENUS" });
fetch(`/api/menus`)
.then(res => res.json())
.then(responseJSON => {
dispatch({ type: "SORT_MENUS", cards: responseJSON });
});
};
};
Reducer:
export default function MenusReducer(
state = {
cards: [],
loading: false
},
action
) {
switch (action.type) {
case "LOADING_MENUS":
return {
...state
};
case "ADD_MENUS":
return {
...state,
cards: action.cards
};
case "SORT_MENUS":
return state.slice().sort(function(menu1, menu2) {
if (menu1.name < menu2.name) return -1;
if (menu1.name < menu2.name) return 1;
return 0;
});
default:
return state;
}
}
Button Component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { sortMenus } from ".././actions/dataActions";
import Row from "react-bootstrap/Row";
import Container from "react-bootstrap/Container";
class SortButton extends Component {
constructor() {
super();
this.state = { menus: [] };
}
handleMenuSort = e => {
this.props.sortMenus()
};
render() {
return (
<Container>
<Row>
<div>
<button id="sort-button" title="Sort Menus" onClick= {this.handleMenuSort}>Sort Menus</button>
</div>
</Row>
</Container>
)
}
}
const mapStateToProps = state => {
return {
menus: state.menus
}
};
const mapDispatchToProps = dispatch => {
return {
sortMenus: params => dispatch(sortMenus(params)),
}
};
export default connect(mapStateToProps, mapDispatchToProps)(SortButton)
Container:
class MainContainer extends Component {
displayCards = () => {
switch(this.props.path) {
case "menus":
return (this.props.menus.cards.map(card => (
<NavLink style={{ color: "black" }} to={`/menus/${card.id}`} key={card.id}><MenuCard view={this.props.displayObject} info={card} /></NavLink>
)));
default:
return (<div>Empty</div>)
}
};
render() {
return (
<CardColumns>
{this.displayCards()}
</CardColumns>
)
}
}
const mapStateToProps = state => {
return {
menus: state.menus
}
};
const mapDispatchToProps = dispatch => {
return {
displayObject: (id, category, type) => dispatch(displayObject(id, category, type)),
}
};
export default connect(mapStateToProps, mapDispatchToProps)(MainContainer)
Your state is an object, not an array. You likely mean to sort the stored cards array.
state.cards.slice(... instead of state.slice(...
case "SORT_MENUS":
return state.cards.slice().sort(function(menu1, menu2) {
if (menu1.name < menu2.name) return -1;
if (menu1.name < menu2.name) return 1;
return 0;
});
Side note: You may also want to clear/set your loading state upon successful data fetching. ;)
EDIT
You are mapping undefined state within mapStateToProps, then mapping over it in the component. Change mapStateToProps to access the correct defined property.
const mapStateToProps = state => ({
cards: state.cards,
});
Then you can iterate over the new cards prop.
case "menus":
return (this.props.cards.map(card => (
<NavLink
style={{ color: "black" }}
to={`/menus/${card.id}`}
key={card.id}
>
<MenuCard view={this.props.displayObject} info={card} />
</NavLink>
)));
You can simply store the fetched menu in application state.
You can have standalone action say SORT_MENU_BY_ALPHABET.
You can simply dispatch this action on button handler as well as on Ajax success. this dispatch may not have any payload associated.
hope it helps.
in reducer you defined state as object and you're trying to do array operation on it. state.slice().
slice is a function available for arrays. so its throwing error.
you should be doing
state.cards.slice().sort((a,b)=> a-b)
i have to implement chat system in react i m doing it first time and i m stuck.i have to pass page no to backend api to get new data every time.and i have to pass page no to api on scroll. i m using
[1]: https://www.npmjs.com/package/react-infinite-scroller
i m getting total data count and 9 data array per page from api.scroll upto which total count is available and when user scroll to top is should load more.i have tried lots of module but failed to implement pagination on scroll.using react-infinite-scroll module i m getting page no but its not working as i want.Please suggest me right way of doing it
here is my component code
const mapStateToProps = state => ({
users: state.sidebarUser.users,
total:state.sidebarUser.total,
routing: state.routing,
converSationId: state.getConversationId.data
});
const mapDispatchToProps = dispatch => ({
loadUserList: (page={}) => (dispatch(getSideBarUser(page))),
getConversationId: (userId) =>
dispatch(getConversationId(userId)),
loadUserContent: id => dispatch(UserChatList(id))
});
class SidebarContainer extends Component {
constructor(props) {
super(props);
this.state={
isLoading:false,
sidebar:[],
page:0,
hasMore: true,
}
this.getPosts=this.getPosts.bind(this);
}
componentDidMount() {
const {
location: { search }
} = this.props.routing;
let userId = new URLSearchParams(search).get("id");
this.props.loadUserList({page:1});
this.setState({page:this.state.page+1});
this.props.getConversationId(userId);
}
getPosts(page) {
console.log("pgae---->",page)
console.log("this.props--->",this.props.users)
this.props.loadUserList({page:page});
}
render() {
const { users } = this.props;
const {hasMore,sidebar} =this.state;
return (
<div className="chatting-user-list-section" ref={(ref) => this.scrollParentRef = ref} >
<InfiniteScroll
initialLoad={false}
pageStart={0}
loadMore={this.getPosts.bind(this)}
hasMore={hasMore}
getScrollParent={() => this.scrollParentRef}
threshold={520}
loader={<div className="loader">Loading ...</div>}>
<SidebarComponent users={users} listClicked={this.listClicked} />
</InfiniteScroll>
</div>)
}
}
export const Sidebar = connect(
mapStateToProps,
mapDispatchToProps
)(SidebarContainer)
and here is my Reducer
import { SIDEBAR_USERS_SUCCESS, SIDEBAR_USERS_FAILURE } from './ActionTypes';
const initialState = {
users: [],
total: 0
}
export const sidebarUser = (state = initialState, { type, payload }) => {
switch (type) {
case SIDEBAR_USERS_SUCCESS: {
return { ...state, ...payload };
}
case SIDEBAR_USERS_FAILURE: {
return { ...state, error: payload }
}
default:
return state;
}
};
I'm trying to set Loader when data is not fetched yet. This scenario would be easy if the data would be uploaded only ones (logic here: set a flag is isFetching to true, when receiving from redux set it to false). But my scenario is a bit different. I'd like to get my data multiple times to update my Calendar component. All is done thru redux with axios package.
It looks like that:
My reducer adds isFetching flag when my axios request is done(the store is updated):
import { ACTIVE_MONTH } from "../actions/types";
export default function(state = null, action){
switch(action.type){
case ACTIVE_MONTH:
return Object.assign({}, state, {
isFetching: false,
fullyBooked: action.payload
})
default:
return state;
}
}
And the component looks like that:
import React, { Component } from 'react';
import Calendar from 'react-calendar';
import ChooseHour from './ChooseHour';
import { connect } from 'react-redux';
import * as actions from '../actions';
class Calendario extends Component {
state = { showHours: false, disabledDates: null}
componentDidMount() {
const { chosenRoom } = this.props;
const date = new Date();
const reqMonth = date.getMonth() + 1;
const reqYear = date.getFullYear();
this.props.activeMonthYearToPass({reqMonth, reqYear, chosenRoom});
}
onChange = date => this.setState({ date }, () => {
const { chosenRoom, isBirthday } = this.props;
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const fullDate = `${year}/${month}/${day}`;
const roomAndDayObj = {fullDate, chosenRoom, isBirthday};
this.props.sendRoomAndDay(roomAndDayObj);
}
);
onClickDay(e) {
const { chosenRoom } = this.props;
!chosenRoom ? this.setState({ errorMsg: "Wybierz pokój", showHours: false}) :
this.setState({ showHours: true, errorMsg:'' });
}
passActiveDate(activeDate) {
const { chosenRoom } = this.props;
const reqMonth = activeDate.getMonth() + 1;
const reqYear = activeDate.getFullYear();
this.setState({ pending: true},
() => this.props.activeMonthYearToPass({reqMonth, reqYear, chosenRoom})
);
this.props.passDateDetails({reqMonth, reqYear});
}
render() {
const { fullyBookedDays, isBirthday } = this.props;
const { errorMsg, pending } = this.state;
return (
<div>
<div className="calendarsCont">
<Calendar
onChange={this.onChange}
onClickDay={(e) => this.onClickDay(e)}
onActiveDateChange={({ activeStartDate }) => this.passActiveDate(activeStartDate)}
value={this.state.date}
locale="pl-PL"
tileDisabled={({date, view}) =>
(view === 'month') &&
fullyBookedDays && fullyBookedDays.fullyBooked.some(item =>
date.getFullYear() === new Date(item).getFullYear() &&
date.getMonth() === new Date(item).getMonth() -1 &&
date.getDate() === new Date(item).getDate()
)}
/>
}
</div>
<p style={{color: 'red'}}>{errorMsg}</p>
<div>
{this.state.showHours ?
<ChooseHour chosenDay={this.state.date} chosenRoom={this.props.chosenRoom} isBirthday={isBirthday}/> :
null}
</div>
</div>
)
}
}
function mapStateToProps({fullyBookedDays}){
return {
fullyBookedDays,
}
}
export default connect (mapStateToProps, actions)(Calendario);
So the new values will come many times from axios request.
What kind of strategy do you use in that case?
THANK YOU!
Whenever there is multiple fetching requests, or even multiple actions that indicates something async is happening and needs to be stored in a part of the state, I use a counter :
export default function(state = {fetchCount: 0}, action){
switch(action.type){
case FETCHING_THING:
return Object.assign({}, state, {
fetchCount: state.fetchCount + 1
})
case FETCHING_THING_DONE:
return Object.assign({}, state, {
fetchCount: state.fetchCount - 1,
fullyBooked: action.payload
}
default:
return state;
}
}
Then you can just check fetchCount > 0 in your mapstatetoprops.
function mapStateToProps({fullyBookedDays, fetchCount}){
return {
fullyBookedDays,
isLoading: fetchCount > 0
}
}
Please take below as an example , Redux-thunk style action is used for wrap multiple axios requests and dispatch them all.
//axios call2
function getData1() {
return axios.get('/data1');
}
//axios call2
function getData2() {
return axios.get('/data2');
}
//redux-thunk action creator
function getFullData() {
return (dispatch, getState) => {
axios.all([getData1(), getData2()])
.then(axios.spread(function (acct, perms) {
//call normal action creator
dispatch(fetchData1())
dispatch(fetchData2())
}));
};
}
//normal actioncreator
function fetchData1(data)
{
return {type: "FETCH_DATA1", payload: data}
}
//normal actioncreator
function fetchData2(data)
{
return {type: "FETCH_DATA2", payload: data}
}
//reducer1:
function reducer1 (state = defaultedState ,action){
return Object.assign({},{...state, data: action.payload, isFetching: false} )
}
//reducer2:
function reducer2 (state = defaultedState ,action){
return Object.assign({},{...state, data: action.payload, isFetching: false} )
}
//component:
mapStateToProps = function(state){
return {
data1: state.data1.data,
data2: state.data2.data,
isFetching1: state.data1.isFetching,
isFetching2: state.data2.isFetching
}
}
import React, { Component } from "react";
class MyComponent extends Component{
render(){
return (!data1 && isFetching1) || (!data2 && isFetching2) ? <Loading> : <DataComponent>
}
}
connect(mapStateToProps)(MyComponent)
I want to change the style of the entire app when a button is pressed. I thought I can do this with a reducer. So I created:
ReducerStyles:
const initialState =
{
name: styleNormal,
path: './styles/styleNormal'
}
export default function reducer01 (state = initialState, action) {
switch (action.type) {
case "changeStyleNormal":
return [
...state,
{
name: name: action.payload,
path: './styles/styleNormal'
}
];
case "changeStyleNew":
return [
...state,
{
name: name: action.payload,
path: './styles/styleNew'
}
];
default:
return state
}
}
And Actions:
const CHANGE_STYLE_NORMAL = 'changeStyleNormal';
const CHANGE_STYLE_NEW = 'changeStyleNew';
export function changeStyleNormal(style){
return {
type: CHANGE_STYLE_NORMAL,
payload: style
}
}
export function changeStyleNew(style){
return {
type: CHANGE_STYLE_NEW,
payload: style
}
}
I created 2 styles in the styles folder so only 1 can be applied depending on the one selected/returned from the reducer. By default I have the styleNormal in the Reducer initialState. Imported the Actions, Reducer is combined and mapStateToProps:
function mapStateToProps(state) {
return {
style: state.style
}
}
function mapDispatchToProps(dispatch) {
return {
changeStyleNormal: (style) => {
dispatch(changeStyleNormal(style));
},
changeStyleNew: (style) => {
dispatch(changeStyleNew(style));
}
}
}
Added 2 buttons:
<TouchableOpacity
style={styles.clickMe}
onPress={()=>this.props.changeStyleNew('styleNew')}>
<Text style={styles.black18}>New Style</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.clickMe}
onPress={()=>this.props.changeStyleNormal('styleNormal')}>
<Text style={styles.black18}>Normal Style</Text>
</TouchableOpacity>
Now when the component is called,
render() {
console.log("style: ",this.props.style);
This gives the style as:
I cannot access this.props.style out of the render() so where would I set the var style = this.props.style.path ?
Also, when I click any button, the actions are fine, but the styles are getting appended to the reducer:
I want only the one passed to be in the reducer. So I can use it to set the style.
Is this the proper way to do it? Please help.
Many thanks.
UPDATE 1:
class Ext2 extends Component {
//console.log('Style:', this.props.people); // <= This throws an internal server error 500
// const styles = this.props.style.path; // same error as above
render() {
console.log("style: ",this.props.style); //<= Works
console.log("stylePath: ",this.props.style.path) //<= Works
I cannot access this.props.style out of the render()
what makes you think you can't access it? you can access this.props from anywhere in the class.
Also, when I click any button, the actions are fine, but the styles
are getting appended to the reducer
Your initial state is an object yet you are returning an array from your reducers:
case "changeStyleNew":
return [
...state,
{
name: name: action.payload,
path: './styles/styleNew'
}
];
Instead try returning an object like this:
case "changeStyleNew":
return{
...state,
name: name: action.payload,
path: './styles/styleNew'
}
EDIT
As a followup to your comment, here is a simple example of how and where you could access this.props outside the render method:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: this.props.count // acess props
};
this.add = this.add.bind(this);
this.sub = this.sub.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({ count: nextProps.count });
}
add() {
this.props.addClick(); // acess props
}
sub() {
this.props.subClick(); // acess props
}
render() {
const { count } = this.state;
return (
<div>
<div>Count:{count} </div>
<button onClick={this.add}>+</button>
<button onClick={this.sub}>-</button>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.addClick = this.addClick.bind(this);
this.subClick = this.subClick.bind(this);
}
addClick() {
const nextstate = this.state.count + 1;
this.setState({ count: nextstate });
}
subClick() {
const nextstate = this.state.count - 1;
this.setState({ count: nextstate });
}
render() {
return (
<div>
<h2>Wellcome to my Counter!</h2>
<Counter
count={this.state.count}
addClick={this.addClick}
subClick={this.subClick}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<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="root"></div>