I want to use rtl layout in my react application. I have used material-ui next version to integrate this application. I have used below code to make application layout rtl. Some components work properly in the rtl layout but some components doesn't affected.
/**
* App.js Layout Start Here
*/
import React, { Component } from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import { MuiThemeProvider } from 'material-ui/styles';
import { IntersectingCirclesSpinner } from 'react-epic-spinners';
import { IntlProvider } from 'react-intl';
import { Redirect, Route } from 'react-router-dom';
import { NotificationContainer } from 'react-notifications';
// app routes
import Dashboard from '../routes/dashboard';
import AppSignUp from '../routes/AppSignUp';
// App locale
import AppLocale from '../lang';
// themes
import lightTheme from './themes/lightTheme';
import darkTheme from './themes/darkTheme';
class App extends Component {
state = {
loading: true
}
componentDidMount() {
let self = this;
setTimeout(() => {
self.setState({ loading: false });
}, 1000);
}
render() {
const { locale, darkMode, rtlLayout } = this.props.settings;
if (this.state.loading) {
return (
<div className="d-flex justify-content-center">
<IntersectingCirclesSpinner color="red" className="rct-loader" />
</div>
);
}
const currentAppLocale = AppLocale[locale.locale];
let theme = '';
if (darkMode) {
theme = darkTheme
} else {
theme = lightTheme
}
if (rtlLayout) {
theme.direction = 'rtl'
} else {
theme.direction = 'ltr'
}
return (
<MuiThemeProvider theme={theme}>
<IntlProvider
locale={currentAppLocale.locale}
messages={currentAppLocale.messages}
>
<React.Fragment>
<NotificationContainer />
<Route path="/dashboard" component={Dashboard} />
<Route path="/signup" component={AppSignUp} />
</React.Fragment>
</IntlProvider>
</MuiThemeProvider>
);
}
}
// map state to props
const mapStateToProps = ({ settings, authUser }) => {
const { user } = authUser;
return { settings, user };
};
export default connect(mapStateToProps)(App);
It doesn't work properly also i have added
<html dir="rtl">...</html>
(1) Don't mutate the theme directly, use getMuiTheme instead:
themeWithDirection = getMuiTheme(theme, { direction: 'rtl' });
Based on: https://github.com/mui-org/material-ui/issues/1926#issuecomment-192736335
(2) Create the RTL component as shown in the Material-UI documentation and put it around your root component:
function RTL(props) {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
{props.children}
</JssProvider>
);
}
return (
<RTL>
<MuiThemeProvider theme={themeWithDirection}>
{/* your component code */}
</MuiThemeProvider>
</RTL>
);
Props to this answer for explicitly showing what to do with the RTL function.
Related
I'm currently attempting to hide the banner at a certain page. I have successfully hid the banner in all other pages except one with a page with a id. I have a dynamic folder named [content]
import { useRouter } from "next/router";
const HIDDEN_BOARDLIST = ["/board/board_list"];
//this is successful
const HIDDEN_BOARDDETAILS = [`board/${content}`].
//this does not work
//http://localhost:3000/board/620471f057aad9002de7f04f. I have to enter the id manually but since this is a dynamic, the id will change every time
export default function Layout(props: ILayoutProps) {
const router = useRouter();
console.log(router.asPath);
const isHiddenBoardList = HIDDEN_BOARDLIST.includes(router.asPath);
return (
<Wrapper>
<Header />
{!isHiddenBoardList && <Banner />}
<BodyWrapper>
<Body>{props.children}</Body>
</BodyWrapper>
</Wrapper>
);
}
useRouter is a hook.
CSR
import React, { useState, useEffect } from 'React';
import { useRouter } from "next/router";
interface ILayoutProps {
//...
}
export default function Layout(props: ILayoutProps) {
const router = useRouter();
const [hidden, setHidden] = useState(false);
useEffect(() => {
if(router.asPath.includes('board/')) {
setHidden(true);
}
}, [router.asPath]);
return (
<Wrapper>
<Header />
{!hidden && <Banner />}
<BodyWrapper>
<Body>{props.children}</Body>
</BodyWrapper>
</Wrapper>
);
}
Since this code is CSR, flickering may occur. <Banner /> will disappear after being rendered.
If you don't want that, there is a way to pass the current url as props of the <Layout /> component via getServerSideProps.
SSR
// pages/board/[id].tsx
import { GetServerSideProps, NextPage } from 'next';
import Head from 'next/head';
interface Props {
url: string;
}
const BoardPage: NextPage<Props> = (props: Props) => {
return (
<>
<Layout {...props} />
</>
);
};
export const getServerSideProps: GetServerSideProps = async (context) => {
const { resolvedUrl } = context; //ex) /board/12345?id=12345
return {
props: {
url: resolvedUrl ,
}, // will be passed to the page component as props
};
};
// components/Layout.tsx
import React, { useState, useEffect } from 'React';
import { useRouter } from "next/router";
interface ILayoutProps {
url: string;
// ...
}
export default function Layout(props: ILayoutProps) {
return (
<Wrapper>
<Header />
{props.url.includes('board/') && <Banner />}
<BodyWrapper>
<Body>{props.children}</Body>
</BodyWrapper>
</Wrapper>
);
}
I hope these two kinds of code are helpful.
I'm trying to integrate Firebase to React using React Context. The React project uses the Able template. When I wrap my App component with ContextProvider, it causes an infinite loop.
Here is the code:
./Firebase/firebase.js
import React, { createContext } from "react";
import { useDispatch } from "react-redux";
import firebaseConfig from "./firebaseConfig";
import app from "firebase/app";
import 'firebase/auth';
import 'firebase/firestore';
import "firebase/database";
import { setLoggedUser } from '../store/actions'
// we create a React Context, for this to be accessible
// from a component later
const FirebaseContext = createContext(null);
export { FirebaseContext };
export default ({ children }) => {
let firebase = {
app: null,
database: null,
};
const dispatch = useDispatch();
// check if firebase app has been initialized previously
// if not, initialize with the config we saved earlier
if (!app.apps.length) {
app.initializeApp(firebaseConfig);
firebase = {
app: app,
database: app.database(),
api: {
getUserProfile,
},
};
}
// function to query logged user from the database and
// fire a Redux action to update the items in real-time
function getUserProfile() {
....
}
};
return <FirebaseContext.Provider value={firebase}>{children}</FirebaseContext.Provider>;
};
./index.js
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import App from "./App/index";
import * as serviceWorker from "./serviceWorker";
import reducer from "./store/reducer";
import config from "./config";
import "./assets/scss/style.scss";
import FirebaseProvider from './Firebase/firebase.js';
const store = createStore(reducer);
const app = (
<Provider store={store}>
<BrowserRouter basename={config.basename}>
<FirebaseProvider> <----- cause infinite loading
<App />
</FirebaseProvider>
</BrowserRouter>
</Provider>
);
ReactDOM.render(app, document.getElementById("root"));
The source code that causes the error is where the loadable import component AdminLayout in App/index.js
./App/index.js
import React, { Component, Suspense } from "react";
import { Switch, Route } from "react-router-dom";
import Loadable from "react-loadable";
import "../../node_modules/font-awesome/scss/font-awesome.scss";
import Loader from "./layout/Loader";
import Aux from "../hoc/_Aux";
import ScrollToTop from "./layout/ScrollToTop";
import routes from "../route";
import { FirebaseContext } from '../Firebase/firebase.js';
const AdminLayout = Loadable({
loader: () => {
debugger
return import("./layout/AdminLayout")}, // Cause Infinite Loading
loading: Loader,
});
const App = () => {
const { app, api } = React.useContext(FirebaseContext);
const menu = routes.map((route, index) => {
return route.component ? (
<Route
key={index}
path={route.path}
exact={route.exact}
name={route.name}
render={(props) => <route.component {...props} />}
/>
) : null;
});
return (
<Aux>
<ScrollToTop>
<Suspense fallback={<Loader />}>
<Switch>
{menu}
<Route path="/" component={AdminLayout} />
</Switch>
</Suspense>
</ScrollToTop>
</Aux>
);
}
export default App;
I lost in the debugging process when I try to know what's going on inside this AdminLayout component. This component is coming from the template.
./App/layout/AdminLayout/index.js
import React, { Component, Suspense } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import Fullscreen from "react-full-screen";
import windowSize from "react-window-size";
import Navigation from "./Navigation";
import NavBar from "./NavBar";
import Breadcrumb from "./Breadcrumb";
import Configuration from "./Configuration";
import Loader from "../Loader";
import routes from "../../../routes";
import Aux from "../../../hoc/_Aux";
import * as actionTypes from "../../../store/actions";
//import '../../../app.scss';
class AdminLayout extends Component {
fullScreenExitHandler = () => {
if (
!document.fullscreenElement &&
!document.webkitIsFullScreen &&
!document.mozFullScreen &&
!document.msFullscreenElement
) {
this.props.onFullScreenExit();
}
};
UNSAFE_componentWillMount() {
if (
this.props.windowWidth > 992 &&
this.props.windowWidth <= 1024 &&
this.props.layout !== "horizontal"
) {
this.props.onUNSAFE_componentWillMount();
}
}
mobileOutClickHandler() {
if (this.props.windowWidth < 992 && this.props.collapseMenu) {
this.props.onUNSAFE_componentWillMount();
}
}
render() {
/* full screen exit call */
document.addEventListener("fullscreenchange", this.fullScreenExitHandler);
document.addEventListener(
"webkitfullscreenchange",
this.fullScreenExitHandler
);
document.addEventListener(
"mozfullscreenchange",
this.fullScreenExitHandler
);
document.addEventListener("MSFullscreenChange", this.fullScreenExitHandler);
const menu = routes.map((route, index) => {
return route.component ? (
<Route
key={index}
path={route.path}
exact={route.exact}
name={route.name}
render={(props) => <route.component {...props} />}
/>
) : null;
});
let mainClass = ["pcoded-wrapper"];
if (
this.props.layout === "horizontal" &&
this.props.subLayout === "horizontal-2"
) {
mainClass = [...mainClass, "container"];
}
return (
<Aux>
<Fullscreen enabled={this.props.isFullScreen}>
<Navigation />
<NavBar />
<div
className="pcoded-main-container"
onClick={() => this.mobileOutClickHandler}
>
<div className={mainClass.join(" ")}>
<div className="pcoded-content">
<div className="pcoded-inner-content">
<Breadcrumb />
<div className="main-body">
<div className="page-wrapper">
<Suspense fallback={<Loader />}>
<Switch>
{menu}
<Redirect from="/" to={this.props.defaultPath} />
</Switch>
</Suspense>
</div>
</div>
</div>
</div>
</div>
</div>
<Configuration />
</Fullscreen>
</Aux>
);
}
}
const mapStateToProps = (state) => {
debugger
return {
defaultPath: state.defaultPath,
isFullScreen: state.isFullScreen,
collapseMenu: state.collapseMenu,
layout: state.layout,
subLayout: state.subLayout,
};
};
const mapDispatchToProps = (dispatch) => {
debugger
return {
onFullScreenExit: () => dispatch({ type: actionTypes.FULL_SCREEN_EXIT }),
onUNSAFE_componentWillMount: () =>
dispatch({ type: actionTypes.COLLAPSE_MENU }),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(windowSize(AdminLayout));
Could anyone have an idea why this is happening or maybe how to debug to find the problem? Thank you.
EDIT: When I import the AdminLayout directly without using Loadable, it works fine. How to make this work using Loadable?
import React, { Component, useState } from "react";
import { createMuiTheme, MuiThemeProvider } from "#material-ui/core/styles";
import Switch from "#material-ui/core/Switch";
import LoginPage from "./Dashboard/Login";
class App extends Component {
state = { darkState: false };
render() {
const { darkState } = this.state;
return (
<MuiThemeProvider
theme={darkState ? this.props.darkTheme : this.props.theme}
>
<div className="App">
<Switch
checked={darkState}
onChange={() => this.setState({ darkState: !darkState })}
/>
<LoginPage />
</div>
</MuiThemeProvider>
);
}
}
export default App;
When it is clicked switch for the first time, the color changes but does not return again.
I see that when I look at the console log it works.
According to Material UI, theme props type is object or func
link document
I've got a Standard React-Redux Application with react router v4, webpack 4 and I'm trying to perform lazy loading of components via loadable-components library, so webpack can create chunks and load them on demand. The problems seems it's always rendering the Dashboard (refer code below) Component inside the <Switch>, no matter the route.
I don't understand the cause. I found a similar problem: React-Router v4 rendering wrong component but matching correctly but it follows a different pattern and I can't or don't understand how to apply that solution into my issue.
I'm posting The main AppContainer and the routes file:
AppContainer.js:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Provider } from 'react-redux'
import ReduxToastr from 'react-redux-toastr'
import 'react-redux-toastr/src/styles/index.scss'
import { Offline, Online } from 'react-detect-offline'
import Footer from 'components/Footer/'
import { Modal, ModalHeader, ModalBody } from 'reactstrap'
import { Translate } from 'react-redux-i18n'
import { PersistGate } from 'redux-persist/integration/react'
import { Router, Switch, Route } from 'react-router-dom'
import PrivateRoute from 'components/PrivateRoute'
import { Dashboard, PasswordReset, PasswordResetEdit, SignIn } from 'routes'
// Layout
import CoreLayout from 'layouts/CoreLayout'
class AppContainer extends Component {
static propTypes = {
history: PropTypes.object.isRequired,
persistor: PropTypes.object.isRequired, // redux-persist
store : PropTypes.object.isRequired
}
render () {
const { history, store, persistor } = this.props
const opened = true
const toastrDefaultTimeout = 8000
const newToastrAlwaysOnTop = false
return (
<div>
<Online>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<div style={{ height: '100%' }}>
<ReduxToastr
timeOut={toastrDefaultTimeout}
newestOnTop={newToastrAlwaysOnTop}
preventDuplicates
position='top-right'
transitionIn='fadeIn'
transitionOut='fadeOut'
progressBar />
<Router history={history}>
<CoreLayout {...this.props} >
<Switch>
<Route exact path='/sign-in' component={SignIn} />
<Route exact path='/passwords/new' component={PasswordReset} />
<Route exact path='/passwords/edit' component={PasswordResetEdit} />
<PrivateRoute exact path='/' component={Dashboard} persistor={persistor} />
</Switch>
</CoreLayout>
</Router>
</div>
</PersistGate>
</Provider>
</Online>
<Offline>
<div className='app'>
<div className='app-body'>
<main className='main align-items-center align-self-center'>
<div className='container'>
<div className='animated fadeIn'>
<Modal isOpen={opened} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}><Translate value={`views.shared.no-internet.title`} /></ModalHeader>
<ModalBody>
<div className='card-block'>
<div className='row'>
<div className='col-sm-12'>
<Translate value='views.shared.no-internet.description' />
</div>
</div>
</div>
</ModalBody>
</Modal>
</div>
</div>
</main>
</div>
<Footer />
</div>
</Offline>
</div>
)
}
}
export default AppContainer
routes/index.js:
// We only need to import the modules necessary for initial render
import loadable from 'loadable-components'
import { hot } from 'react-hot-loader'
// Component split-code (lazy load)
let Dashboard,
SignIn,
PasswordReset,
PasswordResetEdit
// Needed for HMR
if (__DEV__) {
Dashboard = hot(module)(loadable(() => import('./Dashboard')))
PasswordReset = hot(module)(loadable(() => import('./PasswordReset')))
PasswordResetEdit = hot(module)(loadable(() => import('./PasswordResetEdit')))
SignIn = hot(module)(loadable(() => import('./SignIn')))
} else {
Dashboard = loadable(() => import('./Dashboard'))
SignIn = loadable(() => import('./SignIn'))
PasswordReset = loadable(() => import('./PasswordReset'))
PasswordResetEdit = loadable(() => import('./PasswordResetEdit'))
}
export { Dashboard, PasswordReset, PasswordResetEdit, SignIn }
And for anyone curious, here is the PrivateRoute component:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Route, Redirect } from 'react-router-dom'
import { connect } from 'react-redux'
import { validateSession } from 'modules/sessions/session'
const mapStateToProps = state => ({
session: state.session
})
const mapDispatchToProps = (dispatch) => {
return {
validateSession: () => { dispatch(validateSession()) }
}
}
class PrivateRoute extends Component {
componentDidMount () {
this.props.validateSession(this.props.persistor)
}
render () {
const { component: Component, session, ...rest } = this.props
return (
<Route {...rest} render={(routeProps) =>
this.props.session.userSignedIn ? <Component {...routeProps} />
: <Redirect to={{
pathname: '/sign-in',
state: { from: routeProps.location }
}} />
}
/>)
}
}
PrivateRoute.propTypes = {
component: PropTypes.func.isRequired,
persistor: PropTypes.object.isRequired,
session: PropTypes.object.isRequired,
validateSession: PropTypes.func.isRequired
}
export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute)
If I remove the if (_DEV_) block in routes/index.js and always do it like the 'else' block everything works okay, however I lose HMR, meaning I have to refresh the browser to see code changes take effect.
Edit
For anyone wandering where the history prop comes from:
Main app entry point (in webpack.config.js). src/main.js:
import React from 'react'
import ReactDOM from 'react-dom'
import createStore from './store/createStore'
import { hot } from 'react-hot-loader'
import AppContainer from './containers/AppContainer'
import { persistStore } from 'redux-persist'
// ========================================================
// Store Instantiation
// ========================================================
const initialState = window.___INITIAL_STATE__
const { history, store } = createStore(initialState)
// begin periodically persisting the store
let persistor = persistStore(store)
// ========================================================
// Render Setup
// ========================================================
const MOUNT_NODE = document.getElementById('root')
let render = () => {
ReactDOM.render(
<AppContainer store={store} persistor={persistor} history={history} />,
MOUNT_NODE
)
}
// This code is excluded from production bundle
if (__DEV__) {
if (module.hot) {
// Development render functions
const renderApp = render
const renderError = (error) => {
const RedBox = require('redbox-react').default
ReactDOM.render(<RedBox error={error} />, MOUNT_NODE)
}
// Wrap render in try/catch
render = () => {
try {
renderApp()
} catch (error) {
console.error(error)
renderError(error)
}
}
// Setup hot module replacement
module.hot.accept('./containers/AppContainer', () =>
render(require('./containers/AppContainer').default)
)
}
}
// ========================================================
// Go!
// ========================================================
export default hot(module)(render)
render()
createStore.js:
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import { apiMiddleware } from 'redux-api-middleware'
import { createLogger } from 'redux-logger'
import makeRootReducer from './reducers'
import { routerMiddleware } from 'react-router-redux'
// I18n
import { syncTranslationWithStore, loadTranslations, setLocale } from 'react-redux-i18n'
import { translationsObject } from 'translations/index'
// Router history
import createHistory from 'history/createBrowserHistory'
// Raven for Sentry
import Raven from 'raven-js'
import createRavenMiddleware from 'raven-for-redux'
export default (initialState = {}) => {
// ======================================================
// Middleware Configuration
// ======================================================
const logger = createLogger()
const history = createHistory()
const historyMiddleware = routerMiddleware(history)
const middleware = [historyMiddleware, apiMiddleware, thunk, logger]
if (__PROD__) {
Raven.config(`${__SENTRY_DSN__}`).install()
middleware.push(createRavenMiddleware(Raven))
}
// ======================================================
// Store Enhancers
// ======================================================
const enhancers = []
let composeEnhancers = compose
const composeWithDevToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
if (typeof composeWithDevToolsExtension === 'function') {
composeEnhancers = composeWithDevToolsExtension
}
// ======================================================
// Store Instantiation and HMR Setup
// ======================================================
const store = createStore(
makeRootReducer(),
initialState,
composeEnhancers(
applyMiddleware(...middleware),
...enhancers
)
)
store.asyncReducers = {}
// DEPRECATED in react-router v4: To unsubscribe, invoke `store.unsubscribeHistory()` anytime
// store.unsubscribeHistory = browserHistory.listen(updateLocation(store))
if (module.hot) {
const reducers = require('./reducers').default
module.hot.accept('./reducers', () => {
store.replaceReducer(reducers(store.asyncReducers))
})
}
syncTranslationWithStore(store)
store.dispatch(loadTranslations(translationsObject))
store.dispatch(setLocale('es_AR'))
return { history, store }
}
I am learning react and redux.I am building a mock up project ,While running the project there is no error however nothing is rendered when I click the home route,
my container code,
import Home from '../components/Home.js'
import {
editorContentUpdated
} from '../action/index.js'
const mapStateToProps = (state) => {
return {
editorText: state.editorText
};
}
const mapDispatchToProps = (dispatch) => {
console.log('here')
onBlur: (text) => {
console.log('text', text);
dispatch(editorContentUpdated(text));
}
}
export default (mapStateToProps, mapDispatchToProps)(Home);
reducer code,
const editorReducer = (state, action) =>{
if(state == undefined){
return null
}
console.log('editorReducer',action.payload);
switch(action.type){
case 'EDITOR_SELECTED':
return action.payload
break;
case 'CONTENT_UPDATED':
return action.payload
break;
}
return state;
}
export default editorReducer;
action creater,
export const getPreviewContent = (text) =>{
console.log('previewContent', text);
return{
type:'PREVIEW_SELECTED',
data:text
}
}
export const editorContentUpdated =(text) =>{
console.log('editor content', text);
return {
type:'CONTENT_UPDATED',
data:text
}
}
routes.js file,
import React from 'react'
import{Router,Route,IndexRoute,browserHistory} from 'react-router'
import Layout from '../components/Layout.js'
import Home from '../container/editor.js'
import Preview from '../components/Preview.js'
const routes = (
<Router history={browserHistory}>
<Route path='/' component={Layout}>
<IndexRoute component={Home} />
<Route path='preview' component={Preview} />
</Route>
</Router>
);
export default routes;
layout,
import React from 'react'
import {
Link
} from 'react-router'
import {
connect
} from 'react-redux'
var Layout = React.createClass({
render: function() {
var styles = {
paddingRight: '10px'
}
console.log('custom', this.props.custom);
var custom = this.props.custom;
return ( <html >
<head >
<title > {custom.title} < /title> <link rel = 'stylesheet href = '/style.css' / >
</head> <body >
<nav >
<Link style = {styles
}to = '/' > Home < /Link> <
Link to = '/preview' > Preview < /Link> </nav> {
this.props.children
}<script dangerouslySetInnerHTML = {{
__html: 'window.PROPS=' + JSON.stringify(custom)
}}/> <script src = '/bundle.js' / >
</body> </html>);}
});
var wrapper = connect(
function(state) {
return {
custom: state
};
}
);
export default wrapper(Layout);
Home Component,
import React from 'react'
import {
Link
} from 'react-router'
let Home = React.createClass({
getInitialState: function() {
return {
editorText: ''
}
},
updateText: function(event) {
this.setState({
editorText: event.target.value
})
},
render: function() {
let wrapperStyle = {
width: '100%'
}
let editorStyle = {
float: 'left',
width: '50%',
height: 'auto'
}
let previewBoxStyle = {
float: 'left',
height: 'auto',
width: '50%'
}
return ( <
div style = {
wrapperStyle
} >
<
div style = { editorStyle} >
<textarea rows = '10' cols = '50'onChange = {this.updateText}
value = {this.props.editorText}/> </div> </div>);}
});
There is no error in the console, but the home component is not rendered when I click on the home button,Could anyone suggest me where I am going wrong?
In your Home component I cannot see an you exporting the component and hence The component won't be rendered
export the Home component as
export default Home;
Also when you make use of react-redux you need to make the store available to your Components, for that you need to make use of Provider
import { Provider } from 'react-redux'
import React from 'react'
import{Router,Route,IndexRoute,browserHistory} from 'react-router'
import Layout from '../components/Layout.js'
import Home from '../container/editor.js'
import Preview from '../components/Preview.js'
import { createStore } from 'redux'
import EditorReducer from '/path/to/reducer';
....
const store = createStore(EditorReducer )
const routes = (
<Provider store={store}>
<Router history={browserHistory}>
<Route path='/' component={Layout}>
<IndexRoute component={Home} />
<Route path='preview' component={Preview} />
</Route>
</Router>
</Provider>
);
export default routes;