Skip to content

Commit

Permalink
Merge pull request #14419 from storybookjs/chore_docs_addons_force_re…
Browse files Browse the repository at this point in the history
…_render_update

Chore: (Docs) Essentials and addons api (snippets and content) updated
  • Loading branch information
jonniebigodes committed Apr 1, 2021
2 parents 3f279fd + 6d0f135 commit 8a799b2
Show file tree
Hide file tree
Showing 16 changed files with 126 additions and 13 deletions.
18 changes: 18 additions & 0 deletions docs/addons/addons-api.md
Expand Up @@ -179,6 +179,24 @@ This hook gets you the current story's parameter.

If the parameter isn't set, the default value (second argument) is returned instead.

### useGlobals

<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-addons-api-useglobal.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

Extremely useful hook for addons that rely on Storybook [Globals](../essentials/toolbars-and-globals.md).

It allows you to retrieve and update any Storybook Globals you want.

If you use this hook, remember that your component will render a lot, and you may need to optimize for that using [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo) or [`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) or [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback).

---

## Storybook API
Expand Down
20 changes: 19 additions & 1 deletion docs/essentials/toolbars-and-globals.md
Expand Up @@ -121,7 +121,7 @@ In Storybook 6.0, if you set the global option `passArgsFirst: false` for backwa

## Consuming globals from within an addon

If you're working on a Storybook addon and you need to retrieve globals. You can do so, The `@storybook/api` package provides a hook for this scenario, you can use the `useGlobals()` hook to retrieve any globals you want.
If you're working on a Storybook addon and you need to retrieve globals. You can do so, the `@storybook/api` package provides a hook for this scenario, you can use the [`useGlobals()`](../addons/addons-api.md#useglobals) hook to retrieve any globals you want.

Using the ThemeProvider example above, you could expand it to display which current theme is being shown inside a panel like so:

Expand All @@ -134,3 +134,21 @@ Using the ThemeProvider example above, you could expand it to display which curr
/>

<!-- prettier-ignore-end -->

## Updating globals from within an addon

If you're working on a Storybook addon that needs to update the global and refreshes the UI, you can do so. As mentioned previously, the `@storybook/api` package provides the necessary hook for this scenario. You can use the `updateGlobals` function to update any global values you want.

Also, you can use the `@storybook/addons` and `@storybook/core-events` packages together to trigger the refresh.

For example, if you were working on a [toolbar addon](../addons/addon-types.md#toolbars), and you want to refresh the UI and update the global once the user clicks on a button, like so:

<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/addon-consume-and-update-globaltype.js.mdx',
]}
/>

<!-- prettier-ignore-end -->
41 changes: 41 additions & 0 deletions docs/snippets/common/addon-consume-and-update-globaltype.js.mdx
@@ -0,0 +1,41 @@
```js
// your-addon-register-file.js

import React, { useCallback } from 'react';

import { FORCE_RE_RENDER } from '@storybook/core-events';
import { useGlobals } from '@storybook/api';

import { IconButton, Icons } from '@storybook/components';

import { addons } from '@storybook/addons';

const ExampleToolbar = () => {
const [globals, updateGlobals] = useGlobals();

const isActive = globals['my-param-key'] || false;

// Function that will update the global value and trigger a UI refresh.
const refreshAndUpdateGlobal = () => {
// Updates Storybook global value
updateGlobals({
['my-param-key']: !isActive,
}),
// Invokes Storybook's addon API method (with the FORCE_RE_RENDER) event to trigger a UI refresh
addons.getChannel().emit(FORCE_RE_RENDER);
};

const toggleOutline = useCallback(() => refreshAndUpdateGlobal(), [isActive]);

return (
<IconButton
key="Example"
active={isActive}
title="Show a Storybook toolbar"
onClick={toggleOutline}
>
<Icons icon="outline" />
</IconButton>
);
};
```
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.setQueryParams({
Expand Down
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.getQueryParam('bbc');
Expand Down
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
const href = api.getUrlState({
Expand Down
2 changes: 1 addition & 1 deletion docs/snippets/common/storybook-addons-api-on.js.mdx
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.on('some-event', (eventData) => console.log(eventData));
Expand Down
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.selectInCurrentKind('Basic');
Expand Down
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.selectStory('Button', 'Basic');
Expand Down
@@ -1,5 +1,5 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

addons.register('my-organisation/my-addon', (api) => {
api.setQueryParams({
Expand Down
@@ -1,5 +1,8 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js
import React from 'react';

import { useAddonState } from '@storybook/api';

export const Panel = () => {
const [state, setState] = useAddonState('my/addon-id', 'initial state');
Expand Down
6 changes: 5 additions & 1 deletion docs/snippets/common/storybook-addons-api-useapi.js.mdx
@@ -1,5 +1,9 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

import React from 'react';

import { useStorybookApi } from '@storybook/api';

export const Panel = () => {
const state = useStorybookApi();
Expand Down
4 changes: 3 additions & 1 deletion docs/snippets/common/storybook-addons-api-usechannel.js.mdx
@@ -1,7 +1,9 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

import React from 'react';
import { STORY_CHANGED } from '@storybook/core-events';

export const Panel = () => {
const emit = useChannel({
STORY_CHANGED: (...args) => console.log(...args),
Expand Down
19 changes: 19 additions & 0 deletions docs/snippets/common/storybook-addons-api-useglobal.js.mdx
@@ -0,0 +1,19 @@
```js
// /my-addon/register.js

import React from 'react';

import { useGlobals } from '@storybook/api';

export const Panel = () => {
const [globals, updateGlobals] = useGlobals();

const isActive = globals['my-param-key'] || false;

return (
<button onClick={() => updateGlobals({ ['my-param-key']: !isActive })}>
{isActive ? 'Hide me!' : 'Show me!'}
</button>
);
};
```
@@ -1,5 +1,9 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

import React from 'react';

import { useParameter } from '@storybook/api';

export const Panel = () => {
const value = useParameter('parameter-key', 'default value');
Expand Down
@@ -1,5 +1,9 @@
```js
// .storybook/my-addon/register.js
// /my-addon/register.js

import React from 'react';

import { useStorybookState } from '@storybook/api';

export const Panel = () => {
const state = useStorybookState();
Expand Down

0 comments on commit 8a799b2

Please sign in to comment.