formio / react

JSON powered forms for React.js
https://form.io
MIT License
306 stars 271 forks source link

[BUG] this.reactInstance =null on Form #405

Closed ivoscode closed 3 years ago

ivoscode commented 3 years ago

Environment

Please provide as many details as you can:

Expected behavior

I have a custom slider component. Using it in FormBuilder and expecting it to show up in Form and displaying data from submission if provided.

Observed behavior

Custom component works fine in the FormBuilder. It also shows up in Form and is able to submit data. The only problem I cannot set value from form submission, shows only the default value. In the FormBuilder the attachReact is returning an instance which is later needed by setValue function in ReactComponent.js. On the Form it does not. I believe that is a cause of the problem but not sure how to fix it.

Example

import { ReactComponent } from "@formio/react";
import React from "react";
import ReactDOM from "react-dom";
import settingsForm from "./Slider.settingsForm";

class SliderCustomComp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: props.value,
    };
  }
  setValue = (v) => {
    this.setState({ value: v }, () => this.props.onChange(this.state.value));
  };

  render() {
    return (
      <div className="w-full">
        <input
          className="w-full focus:outline-none"
          type="range"
          min={this.props.component.minRange}
          max={this.props.component.maxRange}
          value={this.state.value}
          onChange={(e) => {
            this.setValue(e.target.value);
          }}
        />
        <span>{this.state.value}</span>
      </div>
    );
  }
}

export default class Slider extends ReactComponent {
  constructor(component, options, data) {
    super(component, options, data);
  }

  static get builderInfo() {
    return {
      title: "Slider",
      icon: "sliders",
      group: "Data",
      documentation: "",
      weight: -10,
      schema: Slider.schema(),
    };
  }

  static schema() {
    return ReactComponent.schema({
      type: "sliderCustomComp",
      label: "Default Label",
    });
  }
  static editForm = settingsForm;

  attachReact(element) {
    const instance = ReactDOM.render(
      <SliderCustomComp
        component={this.component} // These are the component settings if you want to use them to render the component.
        value={this.dataValue} // The starting value of the component.
        onChange={this.updateValue} // The onChange event to call when the value changes.}
      />,
      element
    );
    console.log("instance in attachReact", instance);
    return instance;
  }

  /**
   * Automatically detach any react components.
   *
   * @param element
   */
  detachReact(element) {
    if (element) {
      ReactDOM.unmountComponentAtNode(element);
    }
  }
}

This is a console log from FormBuilder. I noticed it does not get the instance right away but it seems the error is causing to execute redraw function and it gets the instance. Screenshot 2021-08-05 at 15 09 58 On the Form it logs out Screenshot 2021-08-05 at 15 52 01

ivoscode commented 3 years ago

Found a solution in case someone needs it. Getting instance via ref and then assigning to this.reactInstance.

attachReact(element) {
    let instance;
    ReactDOM.render(
      <SliderCustomComp
        ref={(refer) => {
          instance = refer;
        }}
        component={this.component} // These are the component settings if you want to use them to render the component.
        value={this.dataValue} // The starting value of the component.
        onChange={this.updateValue} // The onChange event to call when the value changes.}
      />,
      element,
      () => (this.reactInstance = instance)
    );

  }
hokwanhung commented 11 months ago

In some scenarios (hard to say, sometimes it's just by restarting the server or going back and forth via URL), the ref will remain as null, as newer versions of React may render the component asynchronously.

Check this #327 for the newer method to attach ref. It appears to have fewer encounters of the null problem for me.