1

//routes
const AppRoute = () => {
    return (
      <BrowserRouter>
        <div className="container">
          <Switch>
            <Route path='/' component={BooksList} exact/>
            <Route path='/create' component={BookCreate}/>
            <Route path='/books/:id' component={BookShow}/>
          </Switch>
        </div>
      </BrowserRouter>
    );
};
export default AppRoute;

//store 
const store = createStore(reducers, applyMiddleware(Promise));
ReactDOM.render(
  <Provider store={store}>
    <AppRoute/>
  </Provider>,
  document.getElementById("root")
);

I use react and redux. I created a BookShow component to show data of one book. Data loads correctly but when I refresh the page I get this error: Type Error: Cannot read property 'title' of undefined and hole state is undefined.

Why did this happen and how can I prevent it from happening? this is my code

import React from 'react';
import {connect} from 'react-redux'

const BookShow = props => {
  if(!props){
    return <div>loading...</div>
  }
  return (
    <div>
      <h2 className="text-center">{props.book.title}</h2>
      <p className="">{props.book.body}</p>
      {console.log(props)}
    </div>
  );
};

const mapStateToProps = (state, props) => {
  return {
    book: state.books.find((book) => {
      return book.id === props.match.params.id
    })
  }
};
export default connect(mapStateToProps)(BookShow);
ehsan
  • 209
  • 1
  • 4
  • 13
  • Could you please add the relevant code of your routes and the initialization of your redux store? – trixn Mar 15 '18 at 08:54
  • const AppRoute = () => { return (
    ); }; export default AppRoute;
    – ehsan Mar 15 '18 at 09:03
  • You can edit your question. Please add the code there as it is very hard to read otherwise. – trixn Mar 15 '18 at 09:05
  • sorry for that i edit my post – ehsan Mar 15 '18 at 09:11
  • How do you initialy load books to store? and sometimes when using connect you need to use withRouter from react-router-dom to be able to use match,history,location etc. – ivica.moke Mar 15 '18 at 09:16
  • Check this answer https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store/35641992#35641992, once you refresh your redux store is populated with the initialState – Shubham Khatri Mar 15 '18 at 09:26

3 Answers3

0

BookShow is a stateless component, try to make it a class,

import React, { Component } from 'react';

export default class BookShow extends Component {
  render() {
    return (
      <div>
your code...
      </div>
    );
  }
}
Viraj
  • 638
  • 1
  • 8
  • 10
  • how does converting to a class help? – G_S Mar 15 '18 at 09:24
  • reactjs got two type of components, one is components using state which we use class and other one is stateless components, we cant use state in a state less component. – Viraj Mar 15 '18 at 09:42
0
import {withRouter} from 'react-router-dom';

export default withRouter(connect(mapStateToProps)(BookShow));

when you start from homePage and then navigate to some book you can use props.match.params.id but when refreshing page you can't. Try to use withRouter to see if it will fix your problem.

ivica.moke
  • 1,054
  • 2
  • 10
  • 19
0

I have not tested it though! Try it and let me know.

import React from 'react';
import {connect} from 'react-redux'

    class BookShow extends React.Component{
        constructor(props, context) {
            super(props, context);
            this.state = {
                book: {}
            }
        }


        componentWillMount(){
            const { match: { params }, books } = this.props;
            this.state.book = books.find((book) => {
                return book.id === params.id
            });
        }

        render(){
            const { book } = this.props;

            if(!props){
                return <div>loading...</div>
            }

            return (
                <div>
                  <h2 className="text-center">{book.title}</h2>
                  <p className="">{book.body}</p>
                </div>
              );
        }

    }

    const mapStateToProps = (state) => {
      return {
        books: state.books
      }
    };
    export default connect(mapStateToProps)(BookShow);
Neeraj
  • 483
  • 9
  • 17