RickoNoNo3/react-winbox

closed immediately in react v18

kobe651jp opened this issue · 9 comments

When I upgrade react to v18,react-winbox seems works not correctly.

It's worked fine until react v17.

my code as follows.

import { useState } from 'react';
import WinPanel from 'react-winbox';

export default function Example() {
  const [show, setShow] = useState(false);

  return (
    <main className="p-3">
      <div
        className="flex justify-between px-4 py-2 text-sm"
        onClick={() => setShow(true)}
      >
        <span>open</span>
      </div>

      {show && (
        <WinPanel
          width={_.min([document.body.clientWidth, 624])}
          height={_.min([document.body.clientHeight, 400])}
          onclose={() => {
            console.log('winPanel:onclose');
            setTimeout(() => setShow(false));
          }}
          x="center"
          y="center"
          className="z-20"
        >
          hello
        </WinPanel>
      )}
    </main>
  );
}


with or without StrickMode,the result same.
looks like the win-box runs twice.

tien commented

Yeah, also got the same behaviour on React 18.

Recently, I finally got some free time, and will be committed to checking and updating this repo.

After debugging, I found it can be temporarily solved by removing the outermost <React.StrictMode> component of the React application(in index.js/ts if you are using Create React App)

In fact, I deliberately designed this library in versions 16 and 17, so that it conforms to the same behavior in the different rendering environment of strict modes and non-strict modes. I do not know why it has failed in React 18, and I will continue to work on it.

Thank you for your continued following.

My guess is that react 18 rendering twice in default behavior.So I'm trying to control the default behavior to avoid unnecessary rendering.

Here's my code, but it doesn't work.(work in process)

/**
 * winbox for react
 */
import {
  useRef,
  useState,
  useLayoutEffect,
  useEffect,
  useCallback,
  forwardRef,
  useMemo,
} from 'react';
import { createRoot } from 'react-dom/client';
import WinBox from 'winbox/src/js/winbox';
import 'winbox/dist/css/winbox.min.css';
import { dequal } from 'dequal';

function useDeepCompareMemoize(value) {
  const ref = useRef(value);
  const signalRef = useRef(0);

  if (!dequal(value, ref.current)) {
    ref.current = value;
    signalRef.current += 1;
  }
  return useMemo(() => ref.current, [signalRef.current]);
}

function ReactWinbox(props) {
  const winRef = useRef(null);

  useEffect(() => {
    try {
      const { id, title, className, children, onClose, width = 800, height = 450, ...rest } = props;
      const rootComponent = () => <>{children}</>;

      const node = document.getElementById(id);

      winRef.current = new WinBox(title || '', {
        id,
        width,
        height,
        x: 'center',
        y: 'center',
        class: cls('z-50', className || ''),
        mount: node,
        onclose: (force) => {
          if (force) return;
          onClose && onClose();
        },
        ...rest,
      });
      const root = createRoot(winRef.current?.body);
      root.render(<>{React.createElement(rootComponent)}</>);
    } catch (e) {
      winRef.current?.close(true);
    }
  }, [useDeepCompareMemoize(props)]);
}

export default ReactWinbox;

Thank you. I've tried a hack way to avoid the two mounts behavior, it works and only has a little bit invasion. in React 18.2.0, it is in line with our expectation. Versions <=17 are not affected by this.

I just released a new version, now react-winbox@1.4.3. I wonder if you could test it to help me with this.

It's works.Thank you.

The problem now is that the className props seems to work only at first. It would be perfect if the className changed later would also work.

image

I'm working to following up the new version of winbox.js--the author updated this library several months ago, with some new features such as icons and custom controls in the window header. So the function of class state changing can be included into an overall upgraded version. When I complete I will send a signal to you. This issue can be closed now, thanks for your continuing supports, and happy new year!

Now it's on v1.5.0, not only the new features, but a fix to a bug in React 18 I didn't realized before.

This version has a little destructiveness (but just little). Now the css files should be imported manually, and callbacks like onclose have new camel-case names like onClose(the old names can still be used but have been deprecated). You could see the new doc with a new demo.

I tried this new version on my product.It works perfectly.

Thank you for your quick response. This library helps me a lot.