Will get the slug and set up a subscriber to the store so that if the value is changed slug will update and the the component will re-render?
That is correct 👍
Subscriptions from 10,000 feet
I think the mechanisms behind React hooks and store subscriptions can sometimes seem a bit like black magic, and admittedly the details of how they are actually implemented become a little convoluted.
But rhetorically, it may be sufficient to characterize useSelect()
subscriptions as the store keeping track of which components have executed a hook to subscribe to a store’s data. The first time a component executes a subscribing hook, the store adds the component and the callback function which was passed to useSelect()
to a list. If that store’s data changes, the store loops through all of the subscriptions and checks if any callbacks now produce a new value. If they do, the store re-renders the component associated with that callback function/useSelect()
call.
So it’s not really the function call to useSelect()
which triggers a re-render – the first time it runs (or when it’s dependencies change), it just informs an external manager that the component would like to re-render if the callback’s return value changes. And if and when it does change, it is the external manager which will tell the components to re-render. All that the useSelect()
call does during subsequent renders is just return the last value which the callback produced.
I hope that description might dispel some of the magic and make these things a little more intuitive. Though it might instead make it all more confusing and convoluted 😅
How useEntityProp()
creates a subscription/can trigger a render
If I use the setter to update the meta data it seems my component
rerenders. I says seems because I am assuming that this is what is
causing the rerender. I am pretty sure it is this. So – this implies
that something is listening for updates to the meta data and
rerendering when this changes. What is this “something”?
In this case, we can see that useEntityProp()
itself relies upon useSelect()
and a few other hooks:
export default function useEntityProp( kind, name, prop, _id ) {
const providerId = useEntityId( kind, name );
const id = _id ?? providerId;
const { value, fullValue } = useSelect(
( select ) => {
const { getEntityRecord, getEditedEntityRecord } =
select( STORE_NAME );
const record = getEntityRecord( kind, name, id ); // Trigger resolver.
const editedRecord = getEditedEntityRecord( kind, name, id );
return record && editedRecord
? {
value: editedRecord[ prop ],
fullValue: record[ prop ],
}
: {};
},
[ kind, name, id, prop ]
);
const { editEntityRecord } = useDispatch( STORE_NAME );
const setValue = useCallback(
( newValue ) => {
editEntityRecord( kind, name, id, {
[ prop ]: newValue,
} );
},
[ editEntityRecord, kind, name, id, prop ]
);
return [ value, setValue, fullValue ];
}
So the value
and fullValue
values in the array returned from useEntityProps()
are themselves the product of a useSelect()
store subscription. Meanwhile the setValue()
function will execute the editEntityRecord()
action creator on the same store, which will update the record’s value in the store, and if the value actually changes the subscription which was created because of that useSelect()
call will result in the component rendering.
When the documentation fails you, sometimes the source code is a little more willing to share it’s secrets than you might think. It can be worth searching through the GitHub repo, or even getting your IDE set up such that you can jump to the relevant definitions in order to make this sort of exploration a little easier.