Skip to content

Circular dependencies #574

@vinhlh

Description

@vinhlh

Prerequisites

  • I have read the documentation;
  • In the case of a bug report, I understand that providing a SSCCE example is tremendously useful to the maintainers.

Description

Bug

Steps to Reproduce

This is a minimal use case:

import React from 'react'

import SchemaField from 'react-jsonschema-form/lib/components/fields/SchemaField'
import Form from 'react-jsonschema-form'

console.warn(
  'SchemaField.defaultProps.registry.fields.SchemaField',
  SchemaField.defaultProps.registry.fields.SchemaField
)

const CustomSchemaField = function(props) {
  return (
    <div id="custom">
      <p>Yeah, I am pretty dumb.</p>
      <SchemaField {...props} />
    </div>
  );
};

const fields = {
  SchemaField: CustomSchemaField
};

const FormWithCustomSchemaField = () => (
  <Form
    schema={{
      type: 'object',
      properties: {
        title: {
          type: 'string',
          title: 'a title'
        }
      }
    }}
    fields={fields}
    onSubmit={() => {}}
    onChange={() => {}}
  >
    <span />
  </Form>
)

const NormalForm = () => (
  <Form
    schema={{
      type: 'object',
      properties: {
        title: {
          type: 'string',
          title: 'a title'
        }
      }
    }}
    onSubmit={() => {}}
    onChange={() => {}}
  >
    <span />
  </Form>
)

const App = () => (
  <div>
    <FormWithCustomSchemaField />
    <NormalForm />
  </div>
)

export default App

The error is

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `Form`.

This is because of #387 + webpack/webpack#1788

Expected behavior

Should have no error.

Actual behavior

An error, because of undefined SchemaField.

require("./components/fields") = {
  ArrayField: () => () /* component */,
  ...,
  SchemaField: undefined
}

Version

from v0.41.2 to latest (v0.48.0)

Proposal solution

Setting default registry lazily, when react components are instanced, not when they are created.

// utils.js
export function getDefaultRegistry() {
  return {
    fields: require("./components/fields").default,
    widgets: require("./components/widgets").default,
    definitions: {},
    formContext: {},
  };
}

// SchemaField.js
SchemaField.defaultProps = {
  uiSchema: {},
  errorSchema: {},
  idSchema: {},
  registry: null,
  disabled: false,
  readonly: false,
  autofocus: false,
};

function SchemaFieldRender(props) {
  const {
    uiSchema,
    errorSchema,
    idSchema,
    name,
    required,
    registry = getDefaultRegistry()
  } = props;
 // do other things
}

If it's ok, I will create a PR.

cc @n1k0 @dulguun0225 @DanialK

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions