1

I have a problem with my code, I use reactJs and redux.

my error : TypeError: demo.map is not a function

my action:

// DEMO
export const demoFetchRequest = () => {
  return {
    type: DEMO_FETCH_REQUEST,
  };
};
export const demoFetchSuccess = (demo) => {
  return {
    type: DEMO_FETCH_SUCCESS,
    demo,
  };
};
export const demoFetchError = (error) => {
  return {
    type: DEMO_FETCH_ERROR,
    error,
  };
};

my reducer:

const initialState = {
  loading: false,
  demo: [],
  error: null,
};
const demo = (state = initialState, action) => {
  switch (action.type) {
    case DEMO_FETCH_REQUEST:
      return { ...state, loading: true };
    case DEMO_FETCH_SUCCESS:
      return { ...state, loading: false, demo: action.demo };
    case DEMO_FETCH_ERROR:
      return { ...state, loading: false, error: action.error };
    default:
      return state;
  }
};

my data:

const demoCompletedData = [
  {
    id: 1,
    marketId: "1111-1111-1111-1111",
    title: "Autonomous car",
    picture: "https://th?id=OIP.fdvfdvfdvfdvfd&pid=Api",
    language: "English",
    flag: "🇬🇧",
    completed: true,
    date: "22/01/2019 10:30",
    rate: 9.1,
    categories: {
      de: 1,
      sp: 2,
      uk: 0,
      fr: 1,
      us: 4,
    },
  },
  {
    id: 2,

my componentDidMount :

componentDidMount() {
    this.fetchDemo();
    this.fetchUser();
  }

my fetch in front:

 fetchDemo() {
    this.props.demoFetchRequest();
    const { marketId } = this.props.match.params;
    axios.get(`/api/v1/passport-authenticate/market/${marketId}`)
      .then((res) => { return res.data; })
      .then(demo => this.props.demoFetchSuccess(demo))
      .catch(error => this.props.demoFetchError(error));
  }

my return:

const { demo } = this.props;

my render

<h5>{demo.title}</h5>
          <p>
            Demo
            {' '}
            {demo.flag}
          </p>
          {demo.map((el) => {
            return (
              <div>
                {Object.keys(el.categories).map((key) => {
                  return (
                    <p>
                      {key}
                      :
                      {el.categories[key]}
                    </p>
                  );
                })}
              </div>
            );
          })}

and when I change Object.keys() I have another error TypeError: can't convert undefined to object

{Object.keys(demo).map((el) => {
            return (
              <div>
                {Object.keys(el.categories).map((key) => {
                  return (
                    <p>
                      {key}
                      :
                      {el.categories[key]}
                    </p>
                  );
                })}
              </div>
            );
          })}

can you help me ?

7
  • 1
    In addition to your problem, I think using redux-thunk and moving the fetch logic to your action creator would be better. You can trigger different actions (like fetchRequest, the fetch itself) in one function. Commented May 2, 2019 at 8:22
  • @devserkan with thunkMiddleware ? something like demo.service with fetch and demo.action with dispatch ? Commented May 2, 2019 at 9:02
  • Yes, redux-thunk is a middleware for redux to use async operations if you mean this saying by "thunkMiddleware". Commented May 2, 2019 at 9:06
  • Ah, also do not hesitate to accept the answers to your questions if those answers resolve your problem. Commented May 2, 2019 at 9:07
  • I don't know what do you mean by "service" and "action" but here is a simple example of how you do it: codesandbox.io/s/yk519xy7px Look for the auth action. Commented May 2, 2019 at 9:09

1 Answer 1

1

Map is a method on the Array prototype.

The code demo.map will only work if demo is an array, but in your code it appears to be an object.

It looks like your meant your render method to be slightly different, perhaps like:

<h5>{demo.title}</h5>
          <p>
            Demo
            {' '}
            {demo.flag}
          </p>
          {demo.categories.map((el) => {
            return (
              <div>              
                    <p>                      
                      {el}
                    </p>
              </div>
            );
          })}

I also just noticed that your categories is an object, not an array, so the part of your render method that deals with categories should be something like this:

{demo.categories && Object.keys(demo.categories).map((el) => {
            return (
              <div>              
                    <p>                     
                      {el.categories[key]}
                    </p>            
              </div>
            );
          })}

There are some things to note with the above:

  1. If your data is actually an array of demos, not a single demo object, then you need to map that array of demo objects. The way you call demo.title seems to indicate that is might not be that case?
  2. We check that demo.categories actually exists.
  3. Once we have performed Object.keys on the categories object, we no longer need object.keys - the properties of the categories object are simply strings.
Sign up to request clarification or add additional context in comments.

4 Comments

thanks for your help but i have an error : demo.categories is undefined
@user11429164 if it is possible that the categories object is undefined, then you will need to add some code to check if it exists.
As you can see in your previous question, you should map the incoming data first, this is why you can't use map on demo as @DavidHall pointed out. Also, again as he said you need to check your data. You have a loading state, use it. This is why you are keeping it. Conditionally render your data, if loading is true render something else (spinner, etc) then when fetch is completed, render your data.
@devserkan thanks, it's ok i can read data of my object 'categories' now i try to render my data with condtional render.

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.