Gutenberg: Fixing up StrictMode errors in the e2e tests.

Created on 6 Sep 2019  Â·  21Comments  Â·  Source: WordPress/gutenberg

Blocks #14845.

Describe the bug

Turning on StrictMode gives a bunch of errors, this is a tracking ticket to list them out.

I'll list one per comment, along with an e2e test that generates the error.

To reproduce

Run the e2e tests with SCRIPT_DEBUG set to true.

Needs Dev [Type] Bug [Type] Code Quality

All 21 comments

Test: npm run test-e2e packages/e2e-tests/specs/links.test.js

Links › can be created by selecting text and using keyboard shortcuts

    expect(jest.fn()).not.toHaveErrored(expected)

    Expected mock function not to be called but it was called with:
    ["Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s the componentWillUnmount method 
        in URLInput
        in Unknown (created by WithSelect(URLInput))
        in WithSelect(URLInput) (created by WithInstanceId(WithSelect(URLInput)))
        in WithInstanceId(WithSelect(URLInput)) (created by WithSpokenMessages(WithInstanceId(WithSelect(URLInput))))
        in WithSpokenMessages(WithInstanceId(WithSelect(URLInput))) (created by WithSafeTimeout(WithSpokenMessages(WithInstanceId(WithSelect(URLInput)))))
        in WithSafeTimeout(WithSpokenMessages(WithInstanceId(WithSelect(URLInput)))) (created by LinkEditor)
        in form (created by LinkEditor)
        in LinkEditor (created by InlineLinkUI)
        in div (created by URLPopover)
        in div (created by URLPopover)
        in div (created by Animate)
        in div (created by IsolatedEventContainer)
        in IsolatedEventContainer (created by Animate)
        in Animate (created by Popover)
        in PopoverDetectOutside (created by WithFocusOutside(PopoverDetectOutside))
        in div (created by WithFocusOutside(PopoverDetectOutside))
        in WithFocusOutside(PopoverDetectOutside) (created by Popover)
        in Unknown (created by FocusReturn)
        in div (created by FocusReturn)
        in FocusReturn (created by Context.Consumer)
        in WithFocusReturn(Component) (created by WithConstrainedTabbing(WithFocusReturn(Component)))
        in div (created by WithConstrainedTabbing(WithFocusReturn(Component)))
        in WithConstrainedTabbing(WithFocusReturn(Component)) (created by Popover)"]

Test: npm run test-e2e packages/e2e-tests/specs/reusable-blocks.test.js

Reusable Blocks › can be created

    expect(jest.fn()).not.toHaveErrored(expected)

    Expected mock function not to be called but it was called with:
    ["Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s the componentWillUnmount method 
        in SlotComponent (created by Context.Consumer)
        in Slot (created by __experimentalBlockSettingsMenuPluginsExtensionSlot)
        in __experimentalBlockSettingsMenuPluginsExtensionSlot (created by Dropdown)
        in div (created by MenuGroup)
        in div (created by MenuGroup)
        in MenuGroup (created by WithInstanceId(MenuGroup))
        in WithInstanceId(MenuGroup) (created by Dropdown)
        in div (created by NavigableContainer)
        in NavigableContainer (created by ForwardRef(NavigableContainer))
        in ForwardRef(NavigableContainer) (created by ForwardRef(NavigableMenu))
        in ForwardRef(NavigableMenu) (created by Dropdown)
        in div (created by Animate)
        in div (created by IsolatedEventContainer)
        in IsolatedEventContainer (created by Animate)
        in Animate (created by Popover)
        in PopoverDetectOutside (created by WithFocusOutside(PopoverDetectOutside))
        in div (created by WithFocusOutside(PopoverDetectOutside))
        in WithFocusOutside(PopoverDetectOutside) (created by Popover)
        in Unknown (created by FocusReturn)
        in div (created by FocusReturn)
        in FocusReturn (created by Context.Consumer)
        in WithFocusReturn(Component) (created by WithConstrainedTabbing(WithFocusReturn(Component)))
        in div (created by WithConstrainedTabbing(WithFocusReturn(Component)))
        in WithConstrainedTabbing(WithFocusReturn(Component)) (created by Popover)
        in FillComponent (created by Context.Consumer)
        in Fill (created by Context.Consumer)
        in span (created by Context.Consumer)
        in Popover (created by Dropdown)
        in div (created by Dropdown)
        in Dropdown (created by DropdownMenu)
        in DropdownMenu (created by BlockActions)
        in div (created by ToolbarContainer)
        in ToolbarContainer (created by Toolbar)
        in Toolbar (created by BlockActions)
        in BlockActions (created by WithDispatch(BlockActions))
        in WithDispatch(BlockActions)
        in Unknown (created by WithSelect(WithDispatch(BlockActions)))
        in WithSelect(WithDispatch(BlockActions)) (created by BlockSettingsMenu)
        in BlockSettingsMenu (created by BlockToolbar)
        in div (created by BlockToolbar)
        in BlockToolbar
        in Unknown (created by WithSelect(BlockToolbar))
        in WithSelect(BlockToolbar) (created by BlockContextualToolbar)
        in div (created by NavigableContainer)
        in NavigableContainer (created by ForwardRef(NavigableContainer))
        in ForwardRef(NavigableContainer) (created by ForwardRef(NavigableMenu))
        in ForwardRef(NavigableMenu) (created by NavigableToolbar)
        in NavigableToolbar (created by BlockContextualToolbar)
        in BlockContextualToolbar (created by BlockListBlock)
        in div (created by BlockListBlock)
        in div (created by ForwardRef)
        in ForwardRef (created by IgnoreNestedEvents)
        in IgnoreNestedEvents (created by ForwardRef(IgnoreNestedEvents))
        in ForwardRef(IgnoreNestedEvents) (created by BlockListBlock)
        in BlockListBlock
        in Unknown
        in Unknown (created by (BlockListBlock))
        in (BlockListBlock) (created by WithFilters(BlockListBlock))
        in WithFilters(BlockListBlock) (created by IfCondition(WithFilters(BlockListBlock)))
        in IfCondition(WithFilters(BlockListBlock)) (created by WithDispatch(IfCondition(WithFilters(BlockListBlock))))
        in WithDispatch(IfCondition(WithFilters(BlockListBlock)))
        in Unknown (created by WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))
        in WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock))))
        in Unknown (created by Pure(WithViewportMatch(WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))))
        in Pure(WithViewportMatch(WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))) (created by BlockList)
        in BlockAsyncModeProvider (created by BlockList)"]

(I don't know if the SlotComponent errors are all the same thing, or different things with similar symptoms, so posting them all.)

Test: npm run test-e2e packages/e2e-tests/specs/table.test.js

Table › allows header and footer rows to be switched on and off

    expect(jest.fn()).not.toHaveErrored(expected)

    Expected mock function not to be called but it was called with:
    ["Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s the componentWillUnmount method 
        in SlotComponent (created by Context.Consumer)
        in Slot (created by FormatToolbar)
        in div (created by ToolbarContainer)
        in ToolbarContainer (created by Toolbar)
        in Toolbar (created by FormatToolbar)
        in div (created by FormatToolbar)
        in FormatToolbar (created by RichText)
        in FillComponent (created by Context.Consumer)
        in Fill (created by BlockFormatControlsFill)
        in BlockFormatControlsFill (created by Context.Consumer)
        in IfBlockEditSelected(BlockFormatControlsFill) (created by RichText)"]

Test: npm run test-e2e packages/e2e-tests/specs/plugins/meta-attribute-block.test.js

Block with a meta attribute › Should persist the meta attribute properly

    expect(jest.fn()).not.toHaveErrored(expected)

    Expected mock function not to be called but it was called with:
    ["Warning: A component is changing an uncontrolled input of type %s to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s undefined 
        in input (created by edit)
        in edit (created by Edit)
        in Edit (created by WithToolbarControls(Edit))
        in WithToolbarControls(Edit) (created by WithInspectorControl(WithToolbarControls(Edit)))
        in WithInspectorControl(WithToolbarControls(Edit)) (created by WithInspectorControl(WithInspectorControl(WithToolbarControls(Edit))))
        in WithInspectorControl(WithInspectorControl(WithToolbarControls(Edit)))
        in Unknown (created by WithDispatch(Component))
        in WithDispatch(Component)
        in Unknown (created by WithMultipleValidation(WithInspectorControl(WithInspectorControl(WithToolbarControls(Edit)))))
        in WithMultipleValidation(WithInspectorControl(WithInspectorControl(WithToolbarControls(Edit)))) (created by WithFilters(Edit))
        in WithFilters(Edit) (created by BlockEdit)
        in BlockEdit (created by BlockListBlock)
        in BlockCrashBoundary (created by BlockListBlock)
        in div (created by IgnoreNestedEvents)
        in IgnoreNestedEvents (created by ForwardRef(IgnoreNestedEvents))
        in ForwardRef(IgnoreNestedEvents) (created by BlockListBlock)
        in div (created by BlockListBlock)
        in div (created by ForwardRef)
        in ForwardRef (created by IgnoreNestedEvents)
        in IgnoreNestedEvents (created by ForwardRef(IgnoreNestedEvents))
        in ForwardRef(IgnoreNestedEvents) (created by BlockListBlock)
        in BlockListBlock
        in Unknown
        in Unknown (created by (BlockListBlock))
        in (BlockListBlock) (created by WithFilters(BlockListBlock))
        in WithFilters(BlockListBlock) (created by IfCondition(WithFilters(BlockListBlock)))
        in IfCondition(WithFilters(BlockListBlock)) (created by WithDispatch(IfCondition(WithFilters(BlockListBlock))))
        in WithDispatch(IfCondition(WithFilters(BlockListBlock)))
        in Unknown (created by WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))
        in WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock))))
        in Unknown (created by Pure(WithViewportMatch(WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))))
        in Pure(WithViewportMatch(WithSelect(WithDispatch(IfCondition(WithFilters(BlockListBlock)))))) (created by BlockList)
        in BlockAsyncModeProvider (created by BlockList)
        in div (created by BlockList)
        in BlockList (created by WithDispatch(BlockList))
        in WithDispatch(BlockList)
        in Unknown (created by WithSelect(WithDispatch(BlockList)))
        in WithSelect(WithDispatch(BlockList))
        in Unknown (created by VisualEditor)
        in div (created by CopyHandler)
        in CopyHandler (created by WithDispatch(CopyHandler))
        in WithDispatch(CopyHandler) (created by VisualEditor)
        in div (created by ObserveTyping)
        in ObserveTyping (created by WithSafeTimeout(ObserveTyping))
        in WithSafeTimeout(ObserveTyping) (created by WithDispatch(WithSafeTimeout(ObserveTyping)))
        in WithDispatch(WithSafeTimeout(ObserveTyping))
        in Unknown (created by WithSelect(WithDispatch(WithSafeTimeout(ObserveTyping))))
        in WithSelect(WithDispatch(WithSafeTimeout(ObserveTyping))) (created by VisualEditor)
        in div (created by WritingFlow)
        in div (created by WritingFlow)
        in WritingFlow (created by WithDispatch(WritingFlow))
        in WithDispatch(WritingFlow)
        in Unknown (created by WithSelect(WithDispatch(WritingFlow)))
        in WithSelect(WithDispatch(WritingFlow)) (created by VisualEditor)
        in div (created by Typewriter)
        in Typewriter
        in Unknown (created by WithSelect(Typewriter))
        in WithSelect(Typewriter) (created by VisualEditor)
        in div (created by BlockSelectionClearer)
        in BlockSelectionClearer (created by WithDispatch(BlockSelectionClearer))
        in WithDispatch(BlockSelectionClearer)
        in Unknown (created by WithSelect(WithDispatch(BlockSelectionClearer)))
        in WithSelect(WithDispatch(BlockSelectionClearer)) (created by VisualEditor)
        in VisualEditor (created by Layout)
        in div (created by Layout)
        in div (created by FocusReturnProvider)
        in FocusReturnProvider (created by Layout)
        in Layout
        in Unknown (created by WithViewportMatch(Layout))
        in WithViewportMatch(Layout) (created by NavigateRegions(WithViewportMatch(Layout)))
        in div (created by NavigateRegions(WithViewportMatch(Layout)))
        in NavigateRegions(WithViewportMatch(Layout)) (created by WithDispatch(NavigateRegions(WithViewportMatch(Layout))))
        in WithDispatch(NavigateRegions(WithViewportMatch(Layout)))
        in Unknown (created by WithSelect(WithDispatch(NavigateRegions(WithViewportMatch(Layout)))))
        in WithSelect(WithDispatch(NavigateRegions(WithViewportMatch(Layout)))) (created by Editor)
        in ErrorBoundary (created by Editor)
        in BlockEditorProvider (created by WithDispatch(BlockEditorProvider))
        in WithDispatch(BlockEditorProvider)
        in Unknown (created by Context.Consumer)
        in WithRegistryProvider(WithDispatch(BlockEditorProvider)) (created by EditorProvider)
        in EditorProvider (created by WithDispatch(EditorProvider))
        in WithDispatch(EditorProvider)
        in Unknown (created by WithSelect(WithDispatch(EditorProvider)))
        in WithSelect(WithDispatch(EditorProvider))
        in Unknown (created by Context.Consumer)
        in WithRegistryProvider(WithSelect(WithDispatch(EditorProvider))) (created by Editor)
        in div (created by DropZoneProvider)
        in DropZoneProvider (created by Editor)
        in SlotFillProvider (created by Editor)
        in StrictMode (created by Editor)
        in Editor (created by WithDispatch(Editor))
        in WithDispatch(Editor)
        in Unknown (created by WithSelect(WithDispatch(Editor)))
        in WithSelect(WithDispatch(Editor))"]

Test: npm run test-e2e packages/e2e-tests/specs/datepicker.test.js

Datepicker › should show the publishing date if the date is in the past

    expect(jest.fn()).not.toHaveErrored(expected)

    Expected mock function not to be called but it was called with:
    ["Warning: Unsafe lifecycle methods were found within a strict-mode tree:%s

    %s

    Learn more about this warning here:
    https://fb.me/react-strict-mode-warnings 
        in StrictMode (created by Editor)
        in Editor (created by WithDispatch(Editor))
        in WithDispatch(Editor)
        in Unknown (created by WithSelect(WithDispatch(Editor)))
        in WithSelect(WithDispatch(Editor)) componentWillReceiveProps: Please update the following components to use static getDerivedStateFromProps instead: CalendarMonth, CalendarMonthGrid, DayPicker, DayPickerSingleDateController, OutsideClickHandler

    componentWillUpdate: Please update the following components to use componentDidUpdate instead: DayPicker, DayPickerSingleDateController"],["Warning: Legacy context API has been detected within a strict-mode tree: %s

    Please update the following components: %s

    Learn more about this warning here:
    https://fb.me/react-strict-mode-warnings 
        in StrictMode (created by Editor)
        in Editor (created by WithDispatch(Editor))
        in WithDispatch(Editor)
        in Unknown (created by WithSelect(WithDispatch(Editor)))
        in WithSelect(WithDispatch(Editor)) withStyles(CalendarDay), withStyles(CalendarMonth), withStyles(CalendarMonthGrid), withStyles(DayPicker), withStyles(DayPickerNavigation)"]

@pento

I'm seeing these (or possibly related) errors when using a RichText component inside the edit() method of a custom block.

It looks like the errors are coming from the Toolbar components on the RichText control, but I'm not positive.

I've been trying to figure out if I'm doing something wrong (ie trying to mount the components on an unmounted component) but I'm really not a React expert (yet) and I don't know exactly what this means or how to debug it further.

Is this something that's actually coming from a core package or, if this is on me, do you have any advice or recommendations for me on either where to look to learn more about how to do this properly?

Thanks!

Full error (in case it helps):

react-dom.js?ver=16.9.0:539 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in SlotComponent (created by Context.Consumer)
    in Slot (created by FormatToolbar)
    in div (created by ToolbarContainer)
    in ToolbarContainer (created by Toolbar)
    in Toolbar (created by FormatToolbar)
    in div (created by FormatToolbar)
    in FormatToolbar (created by RichText)
    in fill_FillComponent (created by Context.Consumer)
    in Fill (created by BlockFormatControlsFill)
    in BlockFormatControlsFill (created by Context.Consumer)
    in IfBlockEditSelected(BlockFormatControlsFill) (created by RichText)

@gziolo Is this still the case, I think you worked on related things lately?

I was working on different issues lately. This is still valid and it's blocking #14845 - use SCRIPT_DEBUG in end-to-end test environment.

@talldan are you still working on it?

@gziolo Sorry, missed the ping. I think I lost track that I was supposed to be working on this. Sorry!

https://github.com/WordPress/gutenberg/issues/19642 looks like another one related to Slot, might be the same issue.

19642 looks like another one related to Slot, might be the same issue.

@diegohaz is working on a new implementation for SlotFill in https://github.com/WordPress/gutenberg/pull/19242, maybe it will fix this issue?

I'm still seeing those Can't perform a React state update warnings when applying the refactored SlotFill module to BlockControls. Other parts are still using the old implementation though (also because the new SlotFill implementation only supports the current <Slot bubblesVirtually /> scenario, which uses React Portal). I guess that, even if it fixes the warning, we would only get rid of it completely when all the other slots are updated.

By the way, #19242 (slot fill refactor) is kind of done and is blocking other tasks (#20008). I would appreciate any review there! 😆

BTW, the slot fill issue still exists:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in SlotComponent (created by Context.Consumer)
    in Slot (created by Slot)
    in Slot (created by FormatToolbar)
    in div (created by ToolbarGroupContainer)
    in ToolbarGroupContainer (created by ToolbarGroup)
    in ToolbarGroup (created by FormatToolbar)
    in div (created by FormatToolbar)
    in FormatToolbar (created by FormatToolbarContainer)
    in Fill (created by Fill)
    in Fill (created by BlockFormatControlsFill)
    in BlockFormatControlsFill (created by BlockFormatControlsFill)
    in BlockFormatControlsFill (created by Context.Consumer)
    in IfBlockEditSelected(BlockFormatControlsFill) (created by FormatToolbarContainer)
    in FormatToolbarContainer (created by RichText)

I'm also seeing another state update on master:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in ForwardRef(ToolbarContainer) (created by ForwardRef(Toolbar))
    in ForwardRef(Toolbar) (created by NavigableToolbar)
    in NavigableToolbar (created by BlockContextualToolbar)
    in div (created by BlockContextualToolbar)
    in BlockContextualToolbar (created by BlockPopover)
    in div (created by Animate)
    in div (created by ForwardRef)
    in ForwardRef (created by Animate)
    in Animate (created by Popover)
    in PopoverDetectOutside (created by WithFocusOutside(PopoverDetectOutside))
    in div (created by WithFocusOutside(PopoverDetectOutside))
    in WithFocusOutside(PopoverDetectOutside) (created by Popover)
    in Fill (created by Fill)
    in Fill (created by Popover)

You can trigger it by going to post-new.php and clicking between the title and the main editor several times

@noahtallen Does this happen before #20008?

No, I checked out the commit previous to that merge and it does not happen before that PR. I used the same post/post content to test as well. repro steps:

  1. Create a post with a title and a paragraph and save it.
  2. Select the paragraph (so that you could type into it)
  3. Select the ~header~ I mean title (so that you could type into it)
  4. Observe the react warning in the console

_before that PR, step 4 doesn't happen. no warning displays_

Thanks! :)
I'll take a look into that.

thanks for noticing!

Created a simple reproduction here: https://codesandbox.io/s/wordpress-slotfill-memory-leak-warning-nmcmc?file=/src/App.js

It doesn't seem to happen when Slot has bubblesVirtually prop.

It also doesn't happen when we memoize the Fill children (or if it's a primitive value like a string). So my current guess is that it's related to these lines: https://github.com/WordPress/gutenberg/blob/d15a208001f1d728d4f7ffb6b61239fc3fad5fbc/packages/components/src/slot-fill/fill.js#L35-L40

React elements (<div>test</div>) will be always different on every render.

Was this page helpful?
0 / 5 - 0 ratings