2

I created an TextControl inside Popover component, which opens when block toolbar button is pressed. It works fine, with one annoying problem. When user types in TextControl, React redraw of component is triggered and annoying Popover animation happens on each typed character. This does not happen in LinkControl component, which also has Popover as top component. How to achieve this, I could not figure it out from the Gutenberg code? In my excerpt from the code, you'll see that I tried to prevent re-rendering with ref, but without success. I could set animate prop on Popover to be disabled upon text is entered in Textcontrol, but his is not how LinkControl works.

...
    const [isInputDialogVisible, setIsInputDialogVisible] = useState(false);
    // attempt to prevent re-rendering
    const focusOnMount = useRef( 'firstElement' );
    const InputNameDialog = () =>
        <Popover
            onClose={() => { setIsInputDialogVisible(false) }}
            focusOnMount={focusOnMount.current}
        >
            <TextControl
                className='name-attribute'
                label={ _x('Control name', 'Popup control name', 'namespace') }
                help={ _x('This is title of field', 'Popup help text', 'namespace') }
                value={ attributes.nameAutoSet ? '' : attributes.name }
                onChange={ (name) => setName({ name }) }
            />
        </Popover>

...
            <BlockControls group="block">
                <ToolbarButton
                    onClick={() => { setIsInputDialogVisible(true) }}
                    icon="nametag"
                >
                    { isInputDialogVisible && <InputNameDialog /> }
                </ToolbarButton>
            </BlockControls>
...

So, my question is how to set up the code so it works as LinkControl, preventing redrawing of the component when text is entered in TextControl?

1 Answer 1

1

It seems I'll have to answer my question myself :) The solution that I found is using uncontrolled form input component (substituting <TextControl>, or more precisely, I opted to use __experimentalInputControl, with prop isPressEnterToChange={ true }, which only updates control on pressing Enter. I did not inspect the code, but I believe firmly that it is uncontrolled and that uncontrolled <input /> would work as well. This is because uncontrolled component does not trigger react re-render and controlling of the component is given to the browser.

        <InputControl
            // use this in order to have uncontrolled control - otherwise updates trigger popover refresh
            isPressEnterToChange={ true }
            className='name-attribute'
            label={ _x('Control name', 'Popup control name', 'block-form') }
            value={ nameAutoSet ? '' : name }
            onChange={ (name) => { setName( name ); closePopover() } }
            suffix={
                <Button
                    icon={keyboardReturn}
                    onClick={closePopover}
                />
            }
        />

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.