Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

demo-projects/custom-fields: MultiCheck problem with default value #2851

Closed
pahaz opened this issue Apr 28, 2020 · 0 comments · Fixed by #3077
Closed

demo-projects/custom-fields: MultiCheck problem with default value #2851

pahaz opened this issue Apr 28, 2020 · 0 comments · Fixed by #3077

Comments

@pahaz
Copy link
Contributor

pahaz commented Apr 28, 2020

Bug report

Custom fields Cell receive data=null and crash the admin page.

To Reproduce

  1. Run demo-projects/custom-fields
  2. Comment Movie.categories field:
    categories: {
    type: MultiCheck,
    options: ['Action', 'Comedy', 'Drama'],
    defaultValue: [true, false, false],
    },
  3. Create few objects
  4. Uncomment Movie.categories field
  5. Now you have a Movie object without categories it means categories=null
  6. Go to the admin Movie list and you will get an empty page with console error like so:
Uncaught TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at MultiCheckCell (Cell.js:7)
    at renderWithHooks (react-dom.development.js:14803)
    at mountIndeterminateComponent (react-dom.development.js:17482)
    at beginWork (react-dom.development.js:18596)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22154)

And then:

The above error occurred in the <MultiCheckCell> component:
    in MultiCheckCell (at ListTable.js:246)
    in td (created by Context.Consumer)
    in BodyCellTruncated (at ListTable.js:259)
    in tr (created by Context.Consumer)
    in TableRow (at ListTable.js:202)
    in ListRow (at ListTable.js:425)
    in tbody (at ListTable.js:364)
    in TableContents (at ListTable.js:421)
    in Render (at ListTable.js:380)
    in Suspense (at ListTable.js:371)
    in table (created by Context.Consumer)
    in Table (at ListTable.js:370)
    in div (created by Context.Consumer)
    in EmotionCssPropInternal (created by Card)
    in Card (created by Context.Consumer)
    in EmotionCssPropInternal (at ListTable.js:369)
    in ListTable (at List/index.js:215)
    in div (created by Context.Consumer)
    in Styled(div) (at List/index.js:214)
    in main (at List/index.js:99)
    in ListLayout (at List/index.js:331)
    in List (at List/index.js:354)
    in ListData (at client/index.js:81)
    in Route (at client/index.js:77)
    in Switch (at client/index.js:76)
    in ListProvider (at client/index.js:75)
    in Route (at client/index.js:122)
    in Switch (at client/index.js:120)
    in Suspense (at client/index.js:119)
    in div (created by Context.Consumer)
    in Page (at Nav/index.js:487)
    in div (created by Context.Consumer)
    in PageWrapper (at Nav/index.js:432)
    in ResizeHandler (at KeyboardShortcuts.js:75)
    in KeyboardConsumer (at KeyboardShortcuts.js:75)
    in Unknown (at Nav/index.js:418)
    in Nav (at client/index.js:118)
    in ScrollToTop (at client/index.js:117)
    in Route (at client/index.js:116)
    in Switch (at client/index.js:111)
    in Router (created by BrowserRouter)
    in BrowserRouter (at client/index.js:110)
    in ToastProvider (at client/index.js:107)
    in KeyboardShortcuts (at client/index.js:106)
    in ApolloProvider (at client/index.js:105)
    in HooksProvider (at client/index.js:104)
    in KeystoneAdminUI (at client/index.js:146)
    in AdminMetaProvider (at client/index.js:145)
    in Suspense (at client/index.js:144)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

and

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in Search (at List/index.js:129)
    in Render (at List/index.js:122)
    in Suspense (at List/index.js:121)
    in div (created by Context.Consumer)
    in EmotionCssPropInternal (at List/index.js:117)
    in div (created by Context.Consumer)
    in EmotionCssPropInternal (at List/index.js:37)
    in HeaderInset (at List/index.js:103)
    in div (created by Context.Consumer)
    in Styled(div) (at List/index.js:102)
    in main (at List/index.js:99)
    in ListLayout (at List/index.js:331)
    in List (at List/index.js:354)
    in ListData (at client/index.js:81)
    in Route (at client/index.js:77)
    in Switch (at client/index.js:76)
    in ListProvider (at client/index.js:75)
    in Route (at client/index.js:122)
    in Switch (at client/index.js:120)
    in Suspense (at client/index.js:119)
    in div (created by Context.Consumer)
    in Page (at Nav/index.js:487)
    in div (created by Context.Consumer)
    in PageWrapper (at Nav/index.js:432)
    in ResizeHandler (at KeyboardShortcuts.js:75)
    in KeyboardConsumer (at KeyboardShortcuts.js:75)
    in Unknown (at Nav/index.js:418)
    in Nav (at client/index.js:118)
    in ScrollToTop (at client/index.js:117)
    in Route (at client/index.js:116)
    in Switch (at client/index.js:111)
    in Router (created by BrowserRouter)
    in BrowserRouter (at client/index.js:110)
    in ToastProvider (at client/index.js:107)
    in KeyboardShortcuts (at client/index.js:106)
    in ApolloProvider (at client/index.js:105)
    in HooksProvider (at client/index.js:104)
    in KeystoneAdminUI (at client/index.js:146)
    in AdminMetaProvider (at client/index.js:145)
    in Suspense (at client/index.js:144)

Additional context

The problem is here:

return Object.keys(data).map((label, i) => (
<p key={`multicheckcell${label}-${i}`}>{data[label] ? `${label}: true` : `${label}: false`}</p>
));

data is null here!

We can fix lines from here:

export default function MultiCheckCell({ data }) {
// This is the cell in the list table.
// I will return a string of values like: "true, false, true"
return Object.keys(data).map((label, i) => (
<p key={`multicheckcell${label}-${i}`}>{data[label] ? `${label}: true` : `${label}: false`}</p>
));
}

By this path:

export default function MultiCheckCell({ data, field }) {
  // This is the cell in the list table.
  // I will return a string of values like: "true, false, true"
  if (data === null) {
    data = field.getDefaultValue();
  }
  return Object.keys(data).map((label, i) => (
    <p key={`multicheckcell${label}-${i}`}>{data[label] ? `${label}: true` : `${label}: false`}</p>
  ));
}

But, I think the problem is a little deeper. There are two points:

  1. I should receive default value in Cell from the server-side. (now I have a categories: null from the server-side)
  2. I think the admin page should use error boundaries for such cases. If we have a problem with one cell it should not crash the whole page.

@MadeByMike that do you think about it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant