Retool Custom Component (React) updates automatically

Hello! I would like to create a Gantt chart inside Retool (React and TypeScript are main stack). When the Retool page is loaded, chart data is extracted from Retool database. Then I would like to make some changes, for example to extend task date from June 01 to June 03. And only when I extend task date, then data flyes back to Retool and updates the Retool Database. However, I faced with such a behaviour: I extend the date, I see the result for a quick moment and data returns to Retool Database view back. No tasks were updated by me.

I think the solution should be like: to create a local storage, so Retool will not update it until I extend the date and update the Retool DB. Or, maybe, there is a solution to trigger data updates from Retool by some method.

Please, help me with React Custom Component building. This is an example of React-Retool component which receives data and push it back to Retool.

export const RetoolBryntumGantt: FC = () => {
  const [tasksData, _setTasksData] = Retool.useStateArray({
    name: "tasksData",
    initialValue: [],
    label: "Tasks Data",
    description: "Add your tasks-array here."
  });

  const [clickedTaskData, _setClickedTaskData] = Retool.useStateObject({
    name: "clickedTaskData",
    initialValue: {},
    inspector: "hidden",
    label: "Clicked Task Data",
    description: "Here is the data of your clicked task."
  });

  const [resizedTaskData, _setResizedTaskData] = Retool.useStateObject({
    name: "resizedTaskData",
    initialValue: {},
    inspector: "hidden",
    label: "Resized Task Data",
    description: "Here is the data of your resized task."
  });

  const [droppedTaskData, _setDroppedTaskData] = Retool.useStateObject({
    name: "droppedTaskData",
    initialValue: {},
    inspector: "hidden",
    label: "Dropped Task Data",
    description: "Here is the data of your dropped task."
  });

  const setClickedTaskData = (data: any) => {
    _setClickedTaskData(data);
  };

  const setResizedTaskData = (data: any) => {
    _setResizedTaskData(data);
  };

  const setDroppedTaskData = (data: any) => {
    _setDroppedTaskData(data);
  };

  const height = 400;

  const transformedTasksData: Task[] = tasksData.map((task: any) => ({
    id: task.id,
    name: task.name,
    expanded: task.expanded,
    children: task.children.map((subtask: any) => ({
      id: subtask.id,
      name: subtask.name,
      startDate: subtask.startDate,
      endDate: subtask.endDate
    }))
  }));

  ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
      <App tasksData={transformedTasksData} height={height} setClickedTaskData={setClickedTaskData} setResizedTaskData={setResizedTaskData} setDroppedTaskData={setDroppedTaskData} />
    </React.StrictMode>,
  )

  return null;
};

Hi @MrOlegyou

I guess you should update the model in Retool with the new values in order to consolidate the state that needs to be the same both in Retool and in the Custom Component as well.

Hope this help

Hey @abusedmedia, I didn't quite understand your comment. There is no so called Model in a custom component on React. There you can create a field with some data type. Let's say Array or Object and exchange data through this field. I created one field for input in React: tasksData and three fields for output: clickedTaskData, resizedTaskData, droppedTaskData. When one of the fields is updated, the others are also automatically updated. And so I get this behavior: the user clicks on a task and passes the object to Retool. Such an event automatically triggers the incoming tasksData variable and the system returns to the previous state. You get a kind of recursion that lets the data enter React, but in no way lets the data leave React.

Sorry I was referring to the legacy custom component but the strategy should be the same.

In the React Custom Component there's the Retool.useEventCallback that allows you to notify something to Retool.

Usually you can use this to trigger a query in Retool.

I didn't test it yet, but my guess is that when you change the state in the custom component (i.e. with _setShowBorder), it's not synced in Retool automatically and Retool send back the current value set in Retool down to the custom component.

Hey @abusedmedia, thank you for your ideas! You are correct. As I understand, Retool.useEventCallback is possibility to trigger event: React => Retool. However, according to the documentation, event can't pass any data, only triggering. Model of Legacy custom component is what I need because it does not update the Component when you work with data (in/out). I can't understand, how to use legacy Model instead of new useState in the new documentation.

I've never use the new version so far, and I was thinking that the _setSomethingState would automatically update the same state in Retool, if changed within the component, also because there's no equivalent updateModel anymore.

Also in the legacy version the triggerQuery is just a trigger without payload, but using it alongside with the updateModel, it's possible to manage the cross-communication.

Also in the legacy version, when you update the Model, the component gets notified of the model change as well, so you get the same recursion effect you mentioned. But it's pretty easy to workaround it by ignoring it.

To me, this is blocking in adopting this version because state values can be changed from both sides, depending of the situation.

Hey @abusedmedia, do you think that old version will help me with implementing my Custom Component?

Hi, I guess so, but I did a quick test with the new version and it is as I was expecting.

If you use the _setState method within the custom component, the state is changed both in the component and in Retool as well, automatically.

So, you don't really need updateModel anymore.

In the app below I'm changing the custom component state with its internal button and that state is updated also in Retool.

I guess your issue relies on something else.

Hope this help.

Hey @abusedmedia! I have changed the logic of working with data. Every update is now sent directly to Retool Database from the Custom Component, without returning to the Retool App. Thank you for your ideas!

Maybe, you also know something about custom fonts. Because when I try using css style for my Retool Custom Component, style works well, however, icons are broken. The name of the font which works for my Gantt chart is: fa-solid-900.woff2. I tried to import font inside the settings of the app (custom css tab; app theme=>typography tab), however, I see no effects on the Custom Component.

broken_font

I have also this topic, about the same font question:

Maybe @victoria could also help me?

Thanks!

Hi @MrOlegyou I'll close this thread for now as your original question was answered but happy to continue the conversation on your separate thread regarding css/font & bullet points in your custom component :raised_hands:

1 Like