rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.28k stars 2.18k forks source link

custom widgets and React.memo #1309

Closed revolunet closed 2 years ago

revolunet commented 5 years ago

Prerequisites

Description

Looks like the widgets props doesnt like react.memo Components for some reason.

Steps to Reproduce

Once wrapped in React.memo the component is not usable anymore as a form widget. this also impacts react-redux connect wrapper with produces a React.memo :)

Here's a repro : https://codesandbox.io/s/reactredux-connect-with-reactjsonschemaform-issue-8023j

Expected behavior

React memoified components should work :)

Actual behavior

Throws with Unsupported widget definition: object

Version

1.6.0

epicfaace commented 5 years ago

I believe the fix would involve adding ReactIs.isMemo(widget) here: https://github.com/mozilla-services/react-jsonschema-form/blob/41fce4aad12177757eaec823277587aa81166ad2/src/utils.js#L106

coder-guy22296 commented 5 years ago

Is anybody currently working on a fix for this issue?

epicfaace commented 5 years ago

No, not as of now -- @coder-guy22296 would you be able to fix it?

Alexandre27 commented 5 years ago

Can confirm that adding ReactIs.isMemo(widget) solves the problem. I was making a PR to this issue but noticed that custom fields also have a problem with memo components, it's just a warning from propTypes, so its more annoying than anything else. For a custom field I have lots of warnings:

Invalid prop 'fields.customField' of type 'object' supplied to 'Form', expected 'function'

Invalid prop 'registry.fields.customField' of type 'object' supplied to 'SchemaField', expected 'function'.

Invalid prop 'registry.fields.customField' of type 'object' supplied to 'ObjectField', expected 'function'.

Invalid prop 'registry.fields.customField' of type 'object' supplied to 'StringField', expected 'function'.

Invalid prop 'registry.fields.customField' of type 'object' supplied to 'NumberField', expected 'function'.

Invalid prop 'registry.fields.customField' of type 'object' supplied to 'ArrayField', expected 'function'.

I tried adding this to Form.js

    fields: PropTypes.objectOf(
      PropTypes.oneOfType([PropTypes.func, PropTypes.object])
    ),
    ArrayFieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
    ObjectFieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
    FieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

and this to types.js

  ArrayFieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
  FieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
  ObjectFieldTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
  definitions: PropTypes.object.isRequired,
  fields: PropTypes.objectOf(
    PropTypes.oneOfType([PropTypes.func, PropTypes.object])
  )

and it did silence those warnings but a new one appears React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. on MergedWidget.

@epicfaace I'm not very familiar with the entire codebase, any advice on how to fix this one?

RobUnderscore commented 5 years ago

Simple workaround for now if you're using redux connected components -

At the bottom of your custom widget component change:

export default connect(mapStateToProps)(ContractCategorySuperSelect)

to:

var ReduxWrapped = connect(mapStateToProps)(ContractCategorySuperSelect)

class CategorySelectWrapper extends Component {
  render () {
    return (
      <ReduxWrapped {...this.props} />
    )
  }
}

export default CategorySelectWrapper

Essentially just returning a standard react component with the redux connected component inside it.

TheMoonDawg commented 5 years ago

Any word on when this will be fixed?

epicfaace commented 5 years ago

@alexandre27, not sure, but if you make a PR in draft status, it will be easier to inspect what errors you are exactly getting and what might be causing them.

epicfaace commented 5 years ago

Actually, seems like your issue should be solved by using propTypes.elementType: https://github.com/facebook/react/issues/15752

Alexandre27 commented 5 years ago

@epicfaace sorry for the delay, I was on vacations. Created a draft PR with the elementType change but I am getting the same errors. If needed I can create a playground showcasing the error.

epicfaace commented 5 years ago

Fixed by #1447.

travisdahl commented 4 years ago

Still experiencing the same issue with the alpha. Had to use @RobCubed 's solution to work around it

jansenchan commented 4 years ago

Still experiencing the same issue with the v2.0.0.

The test run failed https://github.com/rjsf-team/react-jsonschema-form/blob/v2.0.0/packages/core/test/utils_test.js#L3596 (react-is after v16.9.0).

Because of https://github.com/rjsf-team/react-jsonschema-form/blob/v2.0.0/packages/core/src/utils.js#L114 .

ReactIs.isMemo (after v16.9.0) just judge the React element instance whether a memo component instance. https://github.com/facebook/react/blob/master/packages/react-is/src/ReactIs.js#L31

epicfaace commented 4 years ago

@jansenchan I'm a bit confused... the test passes on CI, are you saying the test fails if you run with a specific React version (v16.9.0)?

jansenchan commented 4 years ago

@jansenchan I'm a bit confused... the test passes on CI, are you saying the test fails if you run with a specific React version (v16.9.0)?

import React from 'react';
import ReactIs from 'react-is';

const C = props => <div {...props} />
const MC = React.memo(C);

// while ReactIs's version is `16.12.0~latest(16.13.1 for now)`
console.log(ReactIs.isMemo(MC)); // false
console.log(ReactIs.isMemo(<MC />)); // true

For the dependencies: "react-is": "^16.9.0", it will resolve react-is@16.13.1, when I install the latest react-jsonschema-form.

You can reinstall the dependencies without package-lock.json and run the test again. The test will fail (while react-is >=16.12.0) .

knilink commented 4 years ago

just checked the file in the react-jsonschema-form/lib/types.js at 1.8.1. that line 17 was still FieldTemplate: _propTypes["default"].func, so probably something wrong with the build or while packing the package?

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please leave a comment if this is still an issue for you. Thank you.