Following the example in the next.js repo: https://github.com/zeit/next.js/tree/v3-beta/examples/with-material-ui
I can get Material-ui working for a single page. And i dont want to do the getInitialProps to set the userAgent prop on every page.
I tried making a HOC that I can use in my pages. But the getInitialProps only works for pages. so my MyMui component cant get the req object.
I tried creating the _document.js page, and wrapped the main with my MuiThemeProvider. But that gives me a bunch of errors.
So how can I get a clean solution to implement material-ui for all my pages?
I ran into a similar issue, and found a solution that looks like this:
// hocs/default-page.js
export default Page => class DefaultPage extends React.Component {
static getInitialProps(ctx) {
// Ensures material-ui renders the correct css prefixes server-side
let userAgent
if (process.browser) {
userAgent = navigator.userAgent
} else {
userAgent = ctx.req.headers['user-agent']
}
// Check if Page has a `getInitialProps`; if so, call it.
const pageProps = Page.getInitialProps && Page.getInitialProps(ctx);
// Return props.
return { ...pageProps, userAgent }
}
...
render() {
return (
<MuiThemeProvider ...>
<Page/>
</MuiThemeProvider>
);
}
}
// pages/index.js
import defaultPage from '../hocs/default-page';
const Page = () => <h1>Hello World</h1>;
Page.getInitialProps = () => { ... };
export default defaultPage(Page);
// Also works for proper components:
export default defaultPage(class MyPage extends React.Component {
static getInitialProps() {
...
}
render() {
...
}
});
layout.js
/**
* Created by Counter on 5/30/2017.
*/
import React, {Component} from 'react'
import Head from 'next/head'
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import Paper from 'material-ui/Paper';
import FlatButton from 'material-ui/FlatButton'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin'
import {blue100, blue400, blue700} from 'material-ui/styles/colors';
import AppBar from 'material-ui/AppBar';
import TextField from 'material-ui/TextField';
// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
try {
if (typeof window !== 'undefined') {
injectTapEventPlugin()
}
} catch (e) {
// do nothing
}
const styles = {
}
const _muiTheme = getMuiTheme({
palette: {
primary1Color: blue400,
primary2Color: blue700,
primary3Color: blue100,
},
});
class Layout extends Component {
render () {
const { userAgent,children } = this.props
/* https://github.com/callemall/material-ui/issues/3336 */
const muiTheme = getMuiTheme(getMuiTheme({userAgent: userAgent}), _muiTheme)
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div>
<Head>
<meta name="viewport" content="initial-scale=1.0, width=device-width"/>
<link rel='stylesheet' href='/static/css/react-md.light_blue-yellow.min.css'/>
</Head>
{children}
</div>
</MuiThemeProvider>
)
}
}
export default Layout
index.js
import React, {Component} from 'react'
import RaisedButton from 'material-ui/RaisedButton'
import Dialog from 'material-ui/Dialog'
import Paper from 'material-ui/Paper';
import FlatButton from 'material-ui/FlatButton'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import injectTapEventPlugin from 'react-tap-event-plugin'
import {blue100,blue400, blue500, blue700,orange500} from 'material-ui/styles/colors';
import Layout from '../component/layout'
import AppBar from 'material-ui/AppBar';
import TextField from 'material-ui/TextField';
import {Tabs, Tab} from 'material-ui/Tabs';
// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
try {
if (typeof window !== 'undefined') {
injectTapEventPlugin()
}
} catch (e) {
// do nothing
}
const styles = {
headline: {
fontSize: 24,
paddingTop: 16,
marginBottom: 12,
fontWeight: 400,
},
contentContainerStyle:{
width:300,
marginTop:133,
float:'left'
},
floatingLabelStyle: {
color: orange500,
},
floatingLabelFocusStyle: {
color: blue500,
},
tabDiv:{
textAlign:'center',
backgroundColor: 'rgb(242, 244, 255);',
boxShadow: '10px 10px 5px #888888',
minHeight:350
},
button: {
margin: 12,
},
descDiv:{
width: '413px',
float: 'left',
margin: '133px 450px 0 25px',
},
outerDiv:{
display:'inline-block'
}
};
const _muiTheme = getMuiTheme({
palette: {
primary1Color: blue400,
primary2Color: blue700,
primary3Color: blue100,
},
});
class Main extends Component {
static getInitialProps ({ req }) {
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
const isServer = !!req
return {isServer, userAgent}
}
constructor (props, context) {
super(props, context);
this.state = {
clicked: false
}
}
render () {
const { userAgent } = this.props;
return(
<Layout userAgent={userAgent} >
<div style={styles.outerDiv}>
<div style={styles.descDiv}>
<p>Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has
survived not only five centuries, but also the leap
into electronic typesetting, remaining essentially
unchanged. It was popularised in the 1960s with the
release of Letraset sheets containing Lorem </p>
<RaisedButton
target="_blank"
label="Test Your Api"
primary={true}
style={styles.button}
icon=''
/>
</div>
<Tabs
value={this.state.value}
onChange={this.handleChange}
style={styles.contentContainerStyle}
>
<Tab label="Login" value="a">
<div style={styles.tabDiv}>
<TextField
floatingLabelText="Username"
floatingLabelStyle={styles.floatingLabelStyle}
floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
/>
<TextField
floatingLabelText="Password"
floatingLabelStyle={styles.floatingLabelStyle}
floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
/>
<br/>
<RaisedButton
target="_blank"
label="Submit"
secondary={true}
style={styles.button}
icon=''
/>
</div>
</Tab>
<Tab label="SignUp" value="b">
<div style={styles.tabDiv}>
<TextField
floatingLabelText="Username"
floatingLabelStyle={styles.floatingLabelStyle}
floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
/>
<TextField
floatingLabelText="Password"
floatingLabelStyle={styles.floatingLabelStyle}
floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
/>
<TextField
floatingLabelText="Confirm Password"
floatingLabelStyle={styles.floatingLabelStyle}
floatingLabelFocusStyle={styles.floatingLabelFocusStyle}
/>
<br/>
<RaisedButton
target="_blank"
label="Submit"
secondary={true}
style={styles.button}
icon=''
/>
</div>
</Tab>
</Tabs>
</div>
</Layout>
)
}
}
export default Main
above files are from my project . i have created layout.js file which i have used in all the pages . this is one way to do it .
Related
I received this error :
Line 21:28: React Hook "useSpring" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks.
I want to make a transition with the opacity and when I click the button appears the image or disappears.
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';
import { useSpring, config, animated } from "react-spring";
import './Experience.css';
class Experience extends Component {
constructor(props) {
super(props);
this.state = {
showA: false
};
}
render() {
// const [showA, setShowA] = useState(false);
const fadeStyles = useSpring({
config: { ...config.molasses },
from: { opacity: 0 },
to: {
opacity: this.state.showA ? 1 : 0
},
});
return (
<div style={{ padding: "15px" }} className="App">
<h2>Fade Demo</h2>
<div>
<animated.div style={fadeStyles}>
<img src={`https://a.wattpad.com/useravatar/valery2080.256.603024.jpg)`} alt="hola"/>
</animated.div>
<br />
<button onClick={() => this.setState(val => !val)}>Toggle</button>
</div>
</div>
);
}
}
export default withTranslation()(Experience);
You need to convert the class component to a functional component. Following is the implementation of Experience Component to a functional component.
Note: Make sure to add the CSS file in your implementation.
Following is the codesandbox link for your reference: https://codesandbox.io/s/jolly-wescoff-bnqm4
import React, { useState, Component } from "react";
import { withTranslation } from "react-i18next";
import { useSpring, config, animated } from "react-spring";
const Experience = () => {
const [showA, setShowA] = useState(false);
const fadeStyles = useSpring({
config: { ...config.molasses },
from: { opacity: 0 },
to: {
opacity: showA ? 1 : 0
}
});
return (
<div style={{ padding: "15px" }} className="App">
<h2>Fade Demo</h2>
<div>
<animated.div style={fadeStyles}>
<img
src={`https://a.wattpad.com/useravatar/valery2080.256.603024.jpg)`}
alt="hola"
/>
</animated.div>
<br />
<button onClick={() => setShowA(!showA)}>Toggle</button>
</div>
</div>
);
};
export default withTranslation()(Experience);
I have a <Button /> component and an <Icon/> component.
I try to implement a button with an icon.
The Button.jsx story:
import React from "react";
import { storiesOf } from "#storybook/react";
import Button from "../components/Button";
import Icon from "../components/Icon/Index";
import { iconTypes } from "../components/Icon/Index";
storiesOf("Button/Primary", module)
.add("With icon", () => (
<Button><Icon type={iconTypes.arrowRight}/></Button>
))
That works fine but I would like the api for a Button with an icon to be-
<Button icon={icons.arrow}>Click Me</Button>
How can I achieve that?
The Icon.jsx story:
import React from "react";
import { storiesOf } from "#storybook/react";
import Icon from "../components/Icon/Index";
import { iconTypes } from "../components/Icon/Index";
storiesOf("Icon", module)
.add("Arrow Right", () => (
<Icon type={iconTypes.arrowRight}>
</Icon>
))
.add("Arrow Left", () => (
<Icon type={iconTypes.arrowLeft}>
</Icon>
));
The <Button /> component:
import React from 'react';
import { css, cx } from 'emotion';
import colors from '../styles/colors';
export default function Button({
children,
...props
}) {
const mergedStyles = cx(
// css
);
// other css stuff
return (
<button {...props} disabled={disabled} className={mergedStyles}>
{children}
</button>
);
And <Icon /> component:
import React from "react";
import { css } from 'emotion';
import ArrowRight from "./arrow-right2.svg";
import ArrowLeft from "./arrow-left2.svg";
export const iconTypes = {
arrowRight: 'ARROW_RIGHT',
arrowLeft: 'ARROW_LEFT',
}
const iconSrc = {
ARROW_RIGHT: ArrowRight,
ARROW_LEFT: ArrowLeft,
}
const circleStyles = css({
width: 24,
height: 24,
borderRadius: "50%",
backgroundColor: "#f7f7f9",
display: "flex",
justifyContent: "center"
});
export default function Icon({ type }) {
return (
<div className={circleStyles}>
<img src={iconSrc[type]} />
</div>
)
};
Any help would be appreciated.
import React from 'react';
import {css, cx} from 'emotion';
import colors from '../styles/colors';
//import your ICON component & make sure your path is right
import Icon from "./../Icon";
export default function Button({
children,
disabled,
icon,
...props
}) {
const mergedStyles = cx(//your css);
return (
<button {...props} disabled={disabled} className={mergedStyles}>
// If icon prop is provided then render ICON component
{icon && <Icon type={icon}/>}
//Other children
{children}
</button>
);
}
in render of Button, you can do something like that :
Button.js:
render(){
const { icon } = this.props
return(
<Button>
{icon && <Icon type={icon}/>}
<Button>
)
}
I'm trying to run some simple unit tests on React with Material UI but I'm getting an error that I don't know the cause of, I've ran tests with MaterialUI on other projects with no problems.
This is the code of the component I'm trying to test:
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import ReactRouterPropTypes from 'react-router-prop-types';
import { Icon } from 'react-fa';
import { withStyles } from 'material-ui/styles';
import AppBar from 'material-ui/AppBar';
import Toolbar from 'material-ui/Toolbar';
import MaterialIcon from 'material-ui/Icon';
import IconButton from 'material-ui/IconButton';
import Modal from 'material-ui/Modal';
import Hidden from 'material-ui/Hidden';
import SimpleButton from '../../common/SimpleButton';
import OutlineButton from '../../common/OutlineButton';
import * as sessionActions from '../../../actions/sessionActions';
import { APP_TITLE, LOGOUT, LOGIN, REGISTER } from '../../../constants/strings';
import { CHECKOUT } from '../../../constants/routes';
import styles from './styles';
import CartIcon from '../../common/Icons/Cart.svg';
import logo from '../../../images/logo.png';
import logoXs from '../../../images/logoXS.png';
import Login from '../Login';
import Register from '../Register';
import Wrapper from '../../common/Wrapper';
class Header extends Component {
constructor(props) {
super(props);
this.state = {};
}
handleLogoutClick = () => {
this.props.actions.logout();
};
handleOpenModal = (s) => {
this.setState({ openModal: s });
};
handleCloseModal = () => {
this.setState({ openModal: null });
};
handleCartIcon = () => {
this.props.history.push(CHECKOUT);
};
renderAuthenticated = () => (
<SimpleButton onClick={this.handleLogoutClick} className={this.props.classes.button}>
{LOGOUT}
</SimpleButton>
);
renderNotAuthenticated = () => {
const { classes, history } = this.props;
return (
<Fragment>
<SimpleButton onClick={() => this.handleOpenModal(LOGIN)} className={classes.button} id="btn-login-modal">
<Hidden smUp>
<Icon className={classes.icons} name="user-circle" alt="login" size="2x" />
</Hidden>
<Hidden xsDown>{LOGIN}</Hidden>
</SimpleButton>
<Modal open={this.state.openModal === LOGIN} onClose={this.handleCloseModal}>
<Login
history={history}
handleCloseModal={this.handleCloseModal}
handleChangeModal={this.handleOpenModal}
/>
</Modal>
<Hidden xsDown>
<OutlineButton
onClick={() => this.handleOpenModal(REGISTER)}
color="primary"
className={classes.button}
>
{REGISTER}
</OutlineButton>
<Modal open={this.state.openModal === REGISTER} onClose={this.handleCloseModal}>
<Register
history={history}
handleCloseModal={this.handleCloseModal}
handleChangeModal={this.handleOpenModal}
/>
</Modal>
</Hidden>
</Fragment>
);
};
render() {
const { authenticated, classes } = this.props;
return (
<AppBar position="static" color="default" className={classes.appBar}>
<Wrapper>
<Toolbar className={classes.toolBar}>
<div className={classes.flex}>
<Hidden smUp>
<img src={logoXs} alt={APP_TITLE} />
</Hidden>
<Hidden xsDown>
<img src={logo} alt={APP_TITLE} />
</Hidden>
</div>
{authenticated ? this.renderAuthenticated() : this.renderNotAuthenticated()}
<IconButton className={classes.button} onClick={() => this.handleCartIcon()}>
<MaterialIcon>
<img src={CartIcon} alt="cart" />
</MaterialIcon>
</IconButton>
</Toolbar>
</Wrapper>
</AppBar>
);
}
}
const { objectOf, any, bool } = PropTypes;
Header.propTypes = {
/* eslint-disable react/no-typos */
classes: objectOf(any).isRequired,
actions: objectOf(any).isRequired,
authenticated: bool.isRequired,
history: ReactRouterPropTypes.history.isRequired,
};
const mapDispatch = dispatch => ({
actions: bindActionCreators(sessionActions, dispatch),
});
const mapStateToProps = ({ session }) => ({
authenticated: session.authenticated,
checked: session.checked,
});
export default connect(mapStateToProps, mapDispatch)(withStyles(styles)(Header));
This is the test file:
import React from 'react';
import { shallow } from 'enzyme';
import Header from './';
import configureStore from '../../../store/configureStore';
const store = configureStore();
const header = shallow(<Header store={store} />);
describe('<Header />', () => {
it('should open modal when clicking `SimpleButton`', () => {
console.log(header.dive().debug());
});
});
And in when I run the tests I get this:
FAIL src/components/containers/Header/Header.test.js ● <Header /> › should open modal when clicking `SimpleButton`
TypeError: Cannot read property '200' of undefined
6 | padding: '10px 5px',
7 | boxShadow: `-webkit-box-shadow: 0px 4px 10px 0px ${
> 8 | theme.palette.gray[200]
9 | }; -moz-box-shadow: 0px 4px 10px 0px ${theme.palette.gray[200]}; box-shadow: 0px 4px 10px 0px ${
10 | theme.palette.gray[200]
11 | }`,
at styles (src/components/containers/Header/styles.js:8:7)
at Object.create (node_modules/material-ui/styles/getStylesCreator.js:31:35)
at WithStyles.attach (node_modules/material-ui/styles/withStyles.js:275:45)
at WithStyles.componentWillMount (node_modules/material-ui/styles/withStyles.js:205:16)
at ReactShallowRenderer._mountClassComponent (node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:137:22)
at ReactShallowRenderer.render (node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:102:14)
at node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:287:35
at withSetStateAllowed (node_modules/enzyme-adapter-utils/build/Utils.js:94:16)
at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:286:68)
at new ShallowWrapper (node_modules/enzyme/build/ShallowWrapper.js:119:22)
at ShallowWrapper.wrap (node_modules/enzyme/build/ShallowWrapper.js:1648:16)
at ShallowWrapper.<anonymous> (node_modules/enzyme/build/ShallowWrapper.js:1718:26)
at ShallowWrapper.single (node_modules/enzyme/build/ShallowWrapper.js:1620:25)
at ShallowWrapper.dive (node_modules/enzyme/build/ShallowWrapper.js:1710:21)
at Object.<anonymous> (src/components/containers/Header/Header.test.js:12:24)
I've tried using mount, wrapping the component in MuiThemeProvider, using the helper createShallow or createMount from MaterialUI.
Nothing works.
AppBar requires a muiTheme context, which you can provide to .dive() (see documentation)
Here is my test for a Header component rendering an AppBar material-ui component.
import React from "react";
import {shallow} from "enzyme";
import Header from "../";
describe("Header", () => {
it("should match the snapshot", () => {
const wrapper = shallow(<Header />);
// dive in AppBar
const wrappedComponents = wrapper.dive({
context: {
muiTheme: {
appBar: "",
zIndex: 0,
prepareStyles: () => {},
button: {
iconButtonSize: 0,
},
},
},
});
expect(wrappedComponents).toMatchSnapshot();
});
});
Been trying for a while to figure out how to set a custom login page in admin-on-rest v-1.0.0
Need to enable email based login. For this I changed the default admin-on-rest login page code slightly (below)
Replaced the UserName with email and changed the authClient to loopbackRestClient
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { propTypes, reduxForm, Field } from 'redux-form';
import { connect } from 'react-redux';
import compose from 'recompose/compose';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { Card, CardActions } from 'material-ui/Card';
import Avatar from 'material-ui/Avatar';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
import CircularProgress from 'material-ui/CircularProgress';
import LockIcon from 'material-ui/svg-icons/action/lock-outline';
import { cyan500, pinkA200 } from 'material-ui/styles/colors';
import defaultTheme from 'admin-on-rest';
import { userLogin as userLoginAction } from 'admin-on-rest';
import Notification from 'admin-on-rest';
const styles = {
main: {
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
alignItems: 'center',
justifyContent: 'center',
},
card: {
minWidth: 300,
},
avatar: {
margin: '1em',
textAlign: 'center ',
},
form: {
padding: '0 1em 1em 1em',
},
input: {
display: 'flex',
},
};
function getColorsFromTheme(theme) {
if (!theme) return { primary1Color: cyan500, accent1Color: pinkA200 };
const {
palette: {
primary1Color,
accent1Color,
},
} = theme;
return { primary1Color, accent1Color };
}
// see http://redux-form.com/6.4.3/examples/material-ui/
const renderInput = ({ meta: { touched, error } = {}, input: { ...inputProps }, ...props }) =>
<TextField
errorText={touched && error}
{...inputProps}
{...props}
fullWidth
/>;
class EmailLogin extends Component {
login = (auth) => this.props.userLogin(auth, this.props.location.state ? this.props.location.state.nextPathname : '/');
render() {
const { handleSubmit, submitting, theme } = this.props;
const muiTheme = getMuiTheme(theme);
const { primary1Color, accent1Color } = getColorsFromTheme(muiTheme);
console.log(styles.form)
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div style={{ ...styles.main, backgroundColor: primary1Color }}>
<Card style={styles.card}>
<div style={styles.avatar}>
<Avatar backgroundColor={accent1Color} icon={<LockIcon />} size={60} />
</div>
<form onSubmit={handleSubmit(this.login)}>
<div style={styles.form}>
<div style={styles.input} >
<Field
name="email"
floatingLabelText={"email"}
component={renderInput}
disabled={submitting}
placeholder={"email"}
/>
</div>
<div style={styles.input}>
<Field
name="password"
component={renderInput}
type="password"
disabled={submitting}
/>
</div>
</div>
<CardActions>
<RaisedButton
type="submit"
primary
disabled={submitting}
icon={submitting && <CircularProgress size={25} thickness={2} />}
fullWidth
/>
</CardActions>
</form>
</Card>
<Notification />
</div>
</MuiThemeProvider>
);
}
}
EmailLogin.propTypes = {
...propTypes,
authClient: PropTypes.func,
previousRoute: PropTypes.string,
theme: PropTypes.object,
userLogin: PropTypes.func.isRequired,
};
EmailLogin.defaultProps = {
theme: defaultTheme,
};
const enhance = compose(
reduxForm({
form: 'signIn',
validate: (values, props) => {
const errors = {};
return errors;
},
}),
connect(null, { userLogin: userLoginAction }),
);
export default enhance( EmailLogin );
I have added the above to the loginPage prop on Admin in my app.js
However admin-on-rest seems to be showing the default page.
I copied the BtcLoginPage from this question
Is there any examples of how to create a custom login page?
But the admin is still showing the default page (the one with UserName) only.
Please do advise. How can I create a custom page using Admin-On-Rest.
Thanks
There is a working example in the admin-on-rest-demo repository:
The custom Login component:
https://github.com/marmelab/admin-on-rest-demo/blob/master/src/Login.js
It's integration into the Admin:
https://github.com/marmelab/admin-on-rest-demo/blob/master/src/App.js#L45
Which version of aor are you using ?
Seems I have been doing something wrong.
My custom loginPage (above) had a silent error. The line
import Notification from 'admin-on-rest';
Was failing it needed to be
import { Notification } from 'admin-on-rest';
However.
Admin-on-rest was implicitly substituting the default admin page for my custom page. I was ascribing the error to my limited knowledge of Redux and React-Redux. But the solution was simpler.
im using react with react-redux and react-router. im working on my blog, in which i have a component with shows list of posts. so everything is working fine but when i get post.id in component it gives me undefined. on the other hand posts are passing to component from container.
please look into my code.
//home_container.js
import { connect } from 'react-redux'
import { show } from './actions'
import HomeComponent from './home_component'
const mapStateToProps = (state) => {
return {
posts: state.posts.data
}
}
const mapDispatchToProps = (dispatch) => {
return {
actions:{
showPosts: (page,limit) => {
show(dispatch,page,limit)
}
}
}
}
const HomeContainer = connect(
mapStateToProps,
mapDispatchToProps
)(HomeComponent)
export default HomeContainer
//home_component.js file
import React, {Component} from 'react';
import Paper from 'material-ui/Paper';
import Style from './styles.css'
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import FlatButton from 'material-ui/FlatButton';
import { Link } from 'react-router'
require('rc-pagination/assets/index.css');
const Pagination = require('rc-pagination');
const style = {
height: "100%",
margin: 10,
padding: 10,
display: 'inline-block',
};
var Detail = React.createClass({
render: function() {
return (
<div >
<div className="row">
<div >
<p>{this.props.post?this.props.post.body.substr(1,600):''}</p>
{this.props.post?
<span style={{"float":"right"}}>
<Link to={`/posts/${this.props.post.id}`}>
<FlatButton
label="Ready more"
labelPosition="before"
primary={true}
/>
</Link>
</span>
:''}
</div>
</div>
</div>
)
}
});
class Index extends Component {
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
componentDidMount(){
this.props.actions.showPosts(1,5)
}
render() {
return (
<div >
{this.props.posts.map((post,i) =>
<div className="row" key={i}>
<Paper
style={style}
zDepth={0}
children={<Detail post={post}/>}
/>
)}
</div>
);
}
}
Index.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
};
export default Index;
i already check through react-redux inspector. i have posts in posts props of this component, which are sets by container through react redux.
so problem is in the following part of above code.
<Link to={`/posts/${this.props.post.id}`}>
<FlatButton
label="Ready more"
labelPosition="before"
primary={true}
/>
</Link>
Link to tag of react router generate url in this form posts/undefined. because it is considering that post.id is undefined. on the other hand each post have id property and i also checked it through inspection of posts objects.
so problem is in this line this.props.post.id