I use Shopify Polaris’s setting toggle.https://polaris.shopify.com/components/actions/setting-toggle#navigation
And I want to implement not only one but multi setting toggles.But I don’t want to always duplicate same handleToggle() and values(contentStatus, textStatus) like below the sandbox A,B,C…
import React, { useCallback, useState } from "react";
import { SettingToggle, TextStyle } from "@shopify/polaris";
export default function SettingToggleExample() {
const [activeA, setActiveA] = useState(false);
const [activeB, setActiveB] = useState(false);
const handleToggleA = useCallback(() => setActiveA((active) => !active), []);
const handleToggleB = useCallback(() => setActiveB((active) => !active), []);
const contentStatusA = activeA ? "Deactivate" : "Activate";
const contentStatusB = activeB ? "Deactivate" : "Activate";
const textStatusA = activeA ? "activated" : "deactivated";
const textStatusB = activeB ? "activated" : "deactivated";
const useHandleToggle = (active, setActive) => {
const handleToggle = useCallback(() => setActive((active) => !active), []);
const contentStatus = active ? "Disconnect" : "Connect";
const textStatus = active ? "connected" : "disconnected";
handleToggle();
return [contentStatus, textStatus];
};
useHandleToggle(activeA, setActiveA);
return (
<>
<SettingToggle
action={{
content: contentStatusA,
onAction: handleToggleA
}}
enabled={activeA}
>
This setting is <TextStyle variation="strong">{textStatusA}</TextStyle>.
</SettingToggle>
<SettingToggle
action={{
content: contentStatusB,
onAction: handleToggleB
}}
enabled={activeB}
>
This setting is <TextStyle variation="strong">{textStatusB}</TextStyle>.
</SettingToggle>
</>
);
}
https://codesandbox.io/s/vigorous-pine-k0dpib?file=/App.js
So I thought I can use a custom hook. But it’s not working. So it would be helpful if you give me some advice.
2
Answers
My first attempt to refactor would use a parameter on the common handler
It functions, but feels a bit naïve. For something more React-ish, a reducer might be the way to go.
With a reducer
This seems cleaner, and is definitely more extensible if you need more toggles.
With a wrapper component
A child component can eliminate the ‘A’ and ‘B’ suffixes
Using simple Booleans for each toggle
If you combine your active state objects into a single array, then you can update as many settings as you would like dynamically. Here’s an example of what that might look like:
Of course, you will likely want to add a label to each of these going forward, so it may be better to define a defaultState object outside the function scope and replace the
Array(2).fill(false)
with it. Then you can have a stringlabel
property for each toggle in addition to a booleanactive
property which can be added next to each toggle in the.map(...)
.With labels added for each toggle
Per your follow up, here is the implementation also found in the CodeSandbox for a state with labels for each toggle (including here on the answer to protect against link decay):