2

Feels like I'm missing something obvious here - but I can't figure out how to access my JSON data. I have a Container component:

class About extends Component {
  componentDidMount(){
    const APP_URL = 'http://localhost/wordpress/'
    const PAGES_URL = `${APP_URL}/wp-json/wp/v2/pages`

    this.props.fetchAllPages(PAGES_URL, 'about')
  }

  render(){
    return (
      <div>
        <Header/>
        <div className="bg">
          <div className="home-wrapper">
            <h1>AAAAABBBBBOOOOUUUUUT</h1>
            <Counter/>
            <AboutInfo />
          </div>
        </div>
        <Footer/>
      </div>
    )
  }
}

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({ fetchAllPages }, dispatch)
}

export default connect(null, mapDispatchToProps)(About);

And a Smart component:

class AboutInfo extends Component {
  render(){
    console.log(this.props.page);
    console.log(this.props.page.id);
    return (
      <div>
        <h1>This is ID: {this.props.page.id}</h1>
      </div>
    )
  }
}

const mapStateToProps = ({ page }) => {
  return { page }
}

export default connect(mapStateToProps)(AboutInfo);

My action:

export const fetchAllPages = (URL, SLUG) => {
  var URLEN;

  if(!SLUG){
    URLEN = URL
  } else {
    URLEN = URL + "?slug=" + SLUG
  }

  return (dispatch) => {
    dispatch(fetchRequest());
    return fetchPosts(URLEN).then(([response, json]) => {
      if(response.status === 200){
        if(!SLUG) {
          dispatch(fetchPagesSuccess(json))
        } else {
          dispatch(fetchPageBySlugSuccess(json))
        }
      } else {
        dispatch(fetchError())
      }
    })
  }
}

const fetchPageBySlugSuccess = (payload) => {
  return {
    type: types.FETCH_PAGE_BY_SLUG,
    payload
  }
}

My reducer:

const page = (state = {}, action) => {
  switch (action.type) {
    case FETCH_PAGE_BY_SLUG:
      console.log(action.paylod)
      return action.payload
    default:
      return state
  }
}

This gives me:

enter image description here

When I console.log(this.props.page) in my AboutInfo component, it prints the object, but when I print console.log(this.props.page.id) it gives me undefined. Why can't I print the JSON content? Thanks!

3
  • page seems to be an array. How about this.props.page[0].id? Commented Mar 14, 2018 at 8:40
  • @HenrikStåhlberg Then I get "Uncaught TypeError: Cannot read property 'id' of undefined" :( Commented Mar 14, 2018 at 8:41
  • The screenshot of the object does not show the whole object. If you extend it at "AboutInfo.js:6" it would be easier to track down the problem. Commented Mar 14, 2018 at 8:45

3 Answers 3

2

page is an array and hence this.props.page.id is undefined. You might want to access the first element in array in which case you would do

this.props.page[0].id

but you might also need to add a test, since before the response is available you will be trying to access page[0].id and it might break.

You could instead write

this.props.page && this.props.page[0] && this.props.page[0].id
Sign up to request clarification or add additional context in comments.

5 Comments

@ShubhamKatri when I try to console.log(this.props.page[0]) or console.log(this.props.page[0].id) I only get "Uncaught TypeError: Cannot read property '0' of undefined" :(
That is the reason I mentioned to add a conditional check
But will I always need to write "<h1>This is ID: {this.props.page && this.props.page[0] && this.props.page[0].id}</h1>" when I want to access a value? @ShubhamKhatri
@fransBernhard, you need to write the conditional check when the data is not initially available. Flow types are really useful in such cases
I've been trying some things, read hackernoon.com/… , but I cant really see how to work it - could you perhaps write an example? Or where I would use Flow types? @ShubhamKhatri
1

Getting data from the store is async So you must adding loading varibale on your reducer

class AboutInfo extends Component {
 render(){
  if(this.props.loading) return (<div>loading</div>);
  return (
   <div>
    <h1>This is ID: {this.props.page.id}</h1>
   </div>
  );
 }
}

const mapStateToProps = ({ page, loading }) => {
 return { page, loading }
}

on your action try returing

json.page[0]

15 Comments

When I try it I get "Uncaught TypeError: Cannot read property '0' of undefined" :(
not this.props.page[0].id do this.props.page.page[0].id
Thank you for answer! When I try dispatch(fetchPageBySlugSuccess(json.page[0]) action I similairly get "Uncaught (in promise) TypeError: Cannot read property '0' of undefined"
use one of this solutions
Still the same issue with this.props.page.page[0].id
|
0

That is because page is an array and the id is a property of its 1st element.

So use this.props.page[0].id

If the logged object in your screenshot is the this.props.page then you will need and additional .page as that is also a part of the object this.props.page.page[0].id

1 Comment

Thank you for response @Gaby , console.log(this.props.page[0].id) and console.log(this.props.page.page[0].id) just gives me "Uncaught TypeError: Cannot read property '0' of undefined" :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.