Skip to content

Commit

Permalink
Remove value syncing in Link Control (#51387)
Browse files Browse the repository at this point in the history
* Remove the syncing

* Update docs with best practices

* Remove unnecessary test coverage

* Implement suggestion sync with previous state

* Apply update from Code Review
  • Loading branch information
getdave authored Oct 9, 2023
1 parent cd0035d commit 0daa67b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
20 changes: 20 additions & 0 deletions packages/block-editor/src/components/link-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ Renders a link control. A link control is a controlled input which maintains a v

It is designed to provide a standardized UI for the creation of a link throughout the Editor, see History section at bottom for further background.

## Best Practices

### Ensuring unique instances

It is possible that a given editor may render multiple instances of the `<LinkControl>` component. As a result, it is important to ensure each instance is unique across the editor to avoid state "leaking" between components.

Why would this happen?

React's reconciliation algorithm means that if you return the same element from a component, it keeps the nodes around as an optimization, even if the props change. This means that if you render two (or more) `<LinkControl>`s, it is possible that the `value` from one will appear in the other as you move between them.

As a result it is recommended that consumers provide a `key` prop to each instance of `<LinkControl>`:

```jsx
<LinkControl key="some-unique-key" { ...props } />
```

This will cause React to return the same component/element type but force remount a new instance, thus avoiding the issues described above.

For more information see: https://github.com/WordPress/gutenberg/pull/34742.

## Relationship to `<URLInput>`

As of Gutenberg 7.4, `<LinkControl>` became the default link creation interface within the Block Editor, replacing previous disparate uses of `<URLInput>` and standardizing the UI.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
/**
* WordPress dependencies
*/
import { useState, useEffect } from '@wordpress/element';
import { useState } from '@wordpress/element';

/**
* External dependencies
*/
import fastDeepEqual from 'fast-deep-equal';

export default function useInternalValue( value ) {
const [ internalValue, setInternalValue ] = useState( value || {} );
const [ previousValue, setPreviousValue ] = useState( value );

// If the value prop changes, update the internal state.
useEffect( () => {
setInternalValue( ( prevValue ) => {
if ( value && value !== prevValue ) {
return value;
}

return prevValue;
} );
}, [ value ] );
// See:
// - https://github.com/WordPress/gutenberg/pull/51387#issuecomment-1722927384.
// - https://react.dev/reference/react/useState#storing-information-from-previous-renders.
if ( ! fastDeepEqual( value, previousValue ) ) {
setPreviousValue( value );
setInternalValue( value );
}

const setInternalURLInputValue = ( nextValue ) => {
setInternalValue( {
Expand Down

0 comments on commit 0daa67b

Please sign in to comment.