React-admin: Cannot read property 'hasOwnProperty' of undefined in edit/show view

Created on 16 Jul 2019  路  4Comments  路  Source: marmelab/react-admin

What you were expecting:
implementing view or show view for items of a ListView

What happened instead:
After implementing List view i tried to implement Edit/Show view as tutorial has done. i'm using ra-data-json-server as my data provider. after clicking on rows in list view the edit/show window is displayed for 2 seconds and then flips back to the list view with this error message: * "Warning: Missing translation for key: "Cannot read property 'hasOwnProperty' of undefined" *

Related code:

App.js: 
function App() {
  return (
    <Admin dataProvider={appdataProvider}>
      <Resource
        name="exerciseInstructionCategory"
        list={ListGuesser}
        edit={EditGuesser}
        show={ShowGuesser}
      />
   </Admin>
Api Response:
{
    "data": {
        "isDeleted": false,
        "updatedAt": "2019-07-15T13:20:56.222Z",
        "image": "https://camo.githubusercontent.com/",
        "title": "varze cate",
        "needsEquipment": false,
        "count": 1,
        "id": "1"
    }
}

Environment

  • React-admin version: 2.9.4
  • React version: 16.8.6
  • Browser: Chrome

Most helpful comment

After some investigation i found out it was because of the response from API (it sent one unnecessary "data" object in the response object) the problem is resolved now and everything is ok but the unhelpful error of react-admin on chrome based browsers (vivaldi, chromium, google chrome) hasn't resolved and the correct error is just logged on firefox browsers which ultimately lead me to the correct solution.
it seems to be browser specific bug in logging errors.
chrome error:
Cannot read property 'hasOwnProperty' of undefined

Firefox:
"The response to '"GET_ONE "' must be like { data: { id: 123, ... } }, but the received data does not have an 'id' key. The dataProvider is probably wrong for "GET_ONE"

All 4 comments

Can you show us the code of your dataprovider?
And better: fork the following CodeSandbox and reproduce your issue from it.

https://codesandbox.io/s/github/marmelab/react-admin/tree/master/examples/simple

I'll try to reproduce it on sandbox but meanwhile this is the data provider code.
dataprovider.js

import { stringify } from "query-string";
import {fetchUtils,GET_LIST,GET_ONE,GET_MANY, GET_MANY_REFERENCE,CREATE,UPDATE,UPDATE_MANY,DELETE,DELETE_MANY
} from "react-admin";
export default (apiUrl, httpClient = fetchUtils.fetchJson) => {
  const convertDataRequestToHTTP = (type, resource, params) => {
    let url = "";
    const options = {};
    switch (type) {
      case GET_LIST: {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
          sort: JSON.stringify([field, order]),
          range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
          filter: JSON.stringify(params.filter)
        };
        url = `${apiUrl}/${resource}?${stringify(query)}`;
        break;
      }
      case GET_ONE:
        url = `${apiUrl}/${resource}/${params.id}`;
        break;
      case GET_MANY: {
        const query = {
          filter: JSON.stringify({ id: params.ids })
        };
        url = `${apiUrl}/${resource}?${stringify(query)}`;
        break;
      }
      case GET_MANY_REFERENCE: {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
          sort: JSON.stringify([field, order]),
          range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
          filter: JSON.stringify({
            ...params.filter,
            [params.target]: params.id
          })
        };
        url = `${apiUrl}/${resource}?${stringify(query)}`;
        break;
      }
      case UPDATE:
        url = `${apiUrl}/${resource}/${params.id}`;
        options.method = "PUT";
        options.body = JSON.stringify(params.data);
        break;
      case CREATE:
        url = `${apiUrl}/${resource}`;
        options.method = "POST";
        options.body = JSON.stringify(params.data);
        break;
      case DELETE:
        url = `${apiUrl}/${resource}/${params.id}`;
        options.method = "DELETE";
        break;
      default:
        throw new Error(`Unsupported fetch action type ${type}`);
    }
    return { url, options };
  };
  const convertHTTPResponse = (response, type, resource, params) => {
    const { headers, json } = response;
    switch (type) {
      case GET_LIST:
      case GET_MANY_REFERENCE:
        if (!headers.has("X-Total-Count")) {
          throw new Error(
            "The Content-Range header is missing in the HTTP Response. The simple REST data provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?"
          );
        }
        return {
          data: json,
          total: parseInt(
            headers
              .get("X-Total-Count")
              .split("/")
              .pop(),
            10
          )
        };
      case CREATE:
        return { data: { ...params.data, id: json.id } };
      default:
        return { data: json };
    }
  };
  return (type, resource, params) => {
    // simple-rest doesn't handle filters on UPDATE route, so we fallback to calling UPDATE n times instead
    if (type === UPDATE_MANY) {
      return Promise.all(
        params.ids.map(id =>
          httpClient(`${apiUrl}/${resource}/${id}`, {
            method: "PUT",
            body: JSON.stringify(params.data)
          })
        )
      ).then(responses => ({
        data: responses.map(response => response.json)
      }));
    }
    // simple-rest doesn't handle filters on DELETE route, so we fallback to calling DELETE n times instead
    if (type === DELETE_MANY) {
      return Promise.all(
        params.ids.map(id =>
          httpClient(`${apiUrl}/${resource}/${id}`, {
            method: "DELETE"
          })
        )
      ).then(responses => ({
        data: responses.map(response => response.json)
      }));
    }

    const { url, options } = convertDataRequestToHTTP(type, resource, params);
    return httpClient(url, options).then(response =>
      convertHTTPResponse(response, type, resource, params)
    );
  };
};

it is based on ra-data-simple-rest.

After some investigation i found out it was because of the response from API (it sent one unnecessary "data" object in the response object) the problem is resolved now and everything is ok but the unhelpful error of react-admin on chrome based browsers (vivaldi, chromium, google chrome) hasn't resolved and the correct error is just logged on firefox browsers which ultimately lead me to the correct solution.
it seems to be browser specific bug in logging errors.
chrome error:
Cannot read property 'hasOwnProperty' of undefined

Firefox:
"The response to '"GET_ONE "' must be like { data: { id: 123, ... } }, but the received data does not have an 'id' key. The dataProvider is probably wrong for "GET_ONE"

Thanks for the investigation!
So, mind you open a new issue describing the enhancement proposal with the issue reproduced on a CodeSandbox fork?

Was this page helpful?
0 / 5 - 0 ratings