Skip to content

Commit

Permalink
Avoid unnecessary renders
Browse files Browse the repository at this point in the history
  • Loading branch information
renatho committed Jul 31, 2024
1 parent 195ea16 commit 8bb0f60
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 27 deletions.
67 changes: 47 additions & 20 deletions assets/blocks/quiz/quiz-block/quiz-validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import {
PluginPostStatusInfo as NewPluginPostStatusInfo,
PluginPrePublishPanel as NewPluginPrePublishPanel,
} from '@wordpress/editor';
import { useCallback } from '@wordpress/element';
import { useCallback, useMemo } from '@wordpress/element';
import { __, _n, sprintf } from '@wordpress/i18n';
import { store as blockEditorStore } from '@wordpress/block-editor';

/**
* Internal dependencies
Expand All @@ -25,6 +26,49 @@ const PluginPostStatusInfo =
const PluginPrePublishPanel =
NewPluginPrePublishPanel || DeprecatedPluginPrePublishPanel;

/**
* Get incomplete questions for a quiz.
*
* @param {string} clientId
* @return {Object[]} Incomplete questions.
*/
const useIncompleteQuestions = ( clientId ) => {
const { questionBlocks } = useSelect(
( select ) => ( {
questionBlocks: select( blockEditorStore ).getBlocks( clientId ),
} ),
[ clientId ]
);

const blockIds = useMemo(
() => questionBlocks.map( ( block ) => block.clientId ),
[ questionBlocks ]
);

const { errors } = useSelect(
( select ) => ( {
errors: select( BLOCK_META_STORE ).getMultipleBlockMeta(
blockIds,
'validationErrors'
),
} ),
[ clientId, blockIds ]
);

const incompleteQuestions = useMemo(
() =>
questionBlocks
.map( ( block ) => ( {
...block,
errors: errors[ block.clientId ],
} ) )
.filter( ( q ) => q.errors?.length ),
[ questionBlocks, errors ]
);

return incompleteQuestions;
};

/**
* Notice about incomplete questions in the quiz.
*
Expand Down Expand Up @@ -70,24 +114,7 @@ const IncompleteQuestionsNotice = ( { count, onClick } ) => (
* @param {Function} props.setMeta
*/
const QuizValidationResult = ( { clientId, setMeta } ) => {
const incompleteQuestions = useSelect(
( select ) => {
const questionBlocks = select( 'core/block-editor' ).getBlocks(
clientId
);
const errors = select( BLOCK_META_STORE ).getMultipleBlockMeta(
questionBlocks.map( ( block ) => block.clientId ),
'validationErrors'
);
return questionBlocks
.map( ( block ) => ( {
...block,
errors: errors[ block.clientId ],
} ) )
.filter( ( q ) => q.errors?.length );
},
[ clientId ]
);
const incompleteQuestions = useIncompleteQuestions( clientId );

const toggleValidationErrors = useCallback(
( on = true ) => {
Expand All @@ -96,7 +123,7 @@ const QuizValidationResult = ( { clientId, setMeta } ) => {
[ setMeta ]
);

const { selectBlock } = useDispatch( 'core/block-editor' );
const { selectBlock } = useDispatch( blockEditorStore );
const selectFirstIncompleteQuestionBlock = () => {
if ( ! incompleteQuestions.length ) return;
toggleValidationErrors( true );
Expand Down
22 changes: 15 additions & 7 deletions assets/shared/blocks/block-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
* WordPress dependencies
*/
import { createHigherOrderComponent } from '@wordpress/compose';
import { dispatch, useDispatch, useSelect } from '@wordpress/data';
import {
dispatch,
useDispatch,
useSelect,
createSelector,
} from '@wordpress/data';
import {
createContext,
useCallback,
Expand Down Expand Up @@ -76,12 +81,15 @@ const store = {
* @param {string} [key] Only return metadata for the given key.
* @return {Object} Blocks metadata, indexed by block ID.
*/
getMultipleBlockMeta: ( state, clientIds = [], key = null ) => {
const blocks = clientIds?.length
? pick( state, clientIds )
: { ...state };
return key ? mapValues( blocks, key ) : blocks;
},
getMultipleBlockMeta: createSelector(
( state, clientIds = [], key = null ) => {
const blocks = clientIds?.length
? pick( state, clientIds )
: { ...state };
return key ? mapValues( blocks, key ) : blocks;
},
( state ) => [ state ]
),
},
};

Expand Down

0 comments on commit 8bb0f60

Please sign in to comment.