javascript - 如何重构代码,使用一个函数代替 4 个函数,每个函数都使用特殊的 `useState` Hook (即 `setAlfaIsTrue(newValue)` )

标签 javascript reactjs react-native

所以我想重构下面的代码,这样我就不必一次又一次地重复它。 我做了一个函数 saveQuestion 但它解决了一半的问题。我不必打电话 setDeleteFilters(true); 再次setFiltersAreApplied(true);... 但是有没有办法每次使用不同的钩子(Hook)调用 saveQuestion 函数,例如使用 setAlfaIsTrue(newValue); 调用一次,然后使用 setBetaIsTrue(newValue); 等? 我认为主要问题是依赖关系......

谢谢:)

const saveQuestion = useCallback(
        () => {
            setDeleteFilters(true);
            setFiltersAreApplied(true);
        },
        [ deleteFilters, filtersAreApplied ]
    );

    const saveAlfa = useCallback(
        (newValue) => {
            setAlfaIsTrue(newValue);
            saveQuestion();
            // setDeleteFilters(true);
            // setFiltersAreApplied(true);
        },
        [ alfaIsTrue ]
    );
    const saveBeta = useCallback(
        (newValue) => {
            setBetaIsTrue(newValue);
            saveQuestion();
            // setDeleteFilters(true);
            // setFiltersAreApplied(true);
        },
        [ betaIsTrue ]
    );

我从 T.J.Crowder 那里得到了我想要的东西 这就是代码现在的样子。 漂亮又简洁。

const [ saveAlfa, saveBeta, saveGamma, saveDelta ] = [
        setAlfaIsTrue,
        setBetaIsTrue,
        setGammaIsTrue,
        setDeltaIsTrue
    ].map((fn, flag) =>
        useCallback((newValue) => {
            fn(newValue);
            setDeleteFilters(true);
            setFiltersAreApplied(true);
        }, [flag])
    );

谢谢 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

这是所有代码: 我仍然需要纠正依赖关系...


const AnswerSwitch = (props) => {
    return (
        <View style={styles.multipleChoiceContainer}>
            {/* <Text style={{color:Colours.moccasin_light}} >{props.label}</Text> */}
            <BoldText>{props.label}</BoldText>
            <View style={{ marginHorizontal: 10 }}>
                <Switch
                    style={{ transform: [ { scaleX: 1 }, { scaleY: 0.7 } ] }}
                    thumbColor={Platform.OS === 'android' ? Colours.maroon : ''}
                    trackColor={Platform.OS === 'android' ? Colours.moccasin_light : ''}
                    value={props.state}
                    onValueChange={props.onChange}
                    disabled={props.disabled}
                />
            </View>
        </View>
    );
};

////////////////////////////////////////////////////////
const DifficultyLevelSettingsScreen = (props) => {
    const { width, height } = Dimensions.get('window');
    const widthMultiplier = DimensionsForStyle.widthMultiplier;
    const textMultiplier = DimensionsForStyle.textMultiplier;
    const cardHeight = DimensionsForStyle.cardHeight;
    const cardWidth = DimensionsForStyle.cardWidth;

    const dispatch = useDispatch();
    const [ isLoading, setIsLoading ] = useState(false);

    // For the switches
    // They run when a switch is touched
    const [ alfaIsTrue, setAlfaIsTrue ] = useState(true);
    const [ betaIsTrue, setBetaIsTrue ] = useState(true);
    const [ gammaIsTrue, setGammaIsTrue ] = useState(true);
    const [ deltaIsTrue, setDeltaIsTrue ] = useState(true);

    // For checking if we have filters on the server so we set their state from there...
    const [ filtersAreApplied, setFiltersAreApplied ] = useState(false);

    // Gets updated everytime we set a filter, so we delete their previous state
    const [ deleteFilters, setDeleteFilters ] = useState(false);

    // Get state of filters from redux to update them
    // const savedFilters = useSelector((state) => state.questions.filters);

    const loadFilters = useCallback(
        async () => {
            const userFilters = await AsyncStorage.getItem('userFilters');
            const savedFilters = JSON.parse(userFilters);

            let applySavedFilters = false;
            for (const key in savedFilters) {
                applySavedFilters = savedFilters[key].filtersAreApplied;
                // If we have savedFilters and we didn't press a switch then...

                if (applySavedFilters && !deleteFilters) {
                    setAlfaIsTrue(savedFilters[key].alfa);
                    setBetaIsTrue(savedFilters[key].beta);
                    setGammaIsTrue(savedFilters[key].gamma);
                    setDeltaIsTrue(savedFilters[key].delta);
                    // setFiltersAreApplied(false)
                }
            }

            // Get state of filters to send them to server
            const appliedFilters = {
                alfa: alfaIsTrue,
                beta: betaIsTrue,
                gamma: gammaIsTrue,
                delta: deltaIsTrue,
                filtersAreApplied: filtersAreApplied
            };
            // If a switch is touched then 'deleteFilters' will be true.
            if (deleteFilters || savedFilters.filtersAreApplied) {
                await dispatch(questionsActions.deletePreviousFilters());
                await dispatch(questionsActions.setFilters(appliedFilters));
            }

            // Fetch them again to update the "initial" state of filters...
            // dispatch(questionsActions.fetchFilters());
        },
        [ alfaIsTrue, betaIsTrue, gammaIsTrue, deltaIsTrue, deleteFilters, filtersAreApplied, dispatch ]
    );

    // loadFilters after focusing
    useEffect(
        () => {
            const willFocusEvent = props.navigation.addListener('willFocus', loadFilters);
            return () => willFocusEvent.remove();
        },
        [ loadFilters ]
    );

    // loadFilters initially...
    useEffect(
        () => {
            setIsLoading(true);
            loadFilters().then(() => setIsLoading(false));
        },
        [ loadFilters ]
    );

    // For setting the email on the HeaderTitle
    useEffect(
        () => {
            const getData = async () => {
                // Note: getItem is asynchronous, so we get a promise
                await dispatch(questionsActions.fetchAllUsersData());
                const userData = await AsyncStorage.getItem('userData');
                if (userData) {
                    // parse converts a string to an object or array
                    const transformedData = JSON.parse(userData);
                    const { userEmail } = transformedData;
                    props.navigation.setParams({ userEmail: userEmail });
                }
            };
            getData();
        },
        [ dispatch ]
    );

    const saveQuestion = useCallback(
        () => {
            // So filters on server will not be deleted
            // when you open the DifficultyLevelSettingsScreen, unless you make a change.
            setDeleteFilters(true);
            setFiltersAreApplied(true);
        },
        [ deleteFilters, filtersAreApplied ]
    );

    // These actions run when the according switch is touched...
    const saveAlfa = useCallback(
        (newValue) => {
            setAlfaIsTrue(newValue);
            saveQuestion()
        },
        [ alfaIsTrue ]
    );
    const saveBeta = useCallback(
        (newValue) => {
            setBetaIsTrue(newValue);
            saveQuestion()
        },
        [ betaIsTrue ]
    );
    const saveGamma = useCallback(
        (newValue) => {
            setGammaIsTrue(newValue);
            saveQuestion()
        },
        [ gammaIsTrue ]
    );
    const saveDelta = useCallback(
        (newValue) => {
            setDeltaIsTrue(newValue);
            saveQuestion()
        },
        [ deltaIsTrue ]
    );

    return (
        // <CustomLinearGradient>
        <ScrollView style={styles.screen}>
            <View style={styles.difficultyLevelStyle}>
                {isLoading ? (
                    <ActivityIndicator size="small" color={Colours.maroon} />
                ) : (
                    <BoldText style={styles.title}>Επιλογή βαθμού (ή βαθμών) δυσκολίας</BoldText>
                )}

                <View style={styles.switchesSummary}>
                    <AnswerSwitch
                        state={alfaIsTrue}
                        // onChange={(newValue) => setAlfaIsTrue(newValue)}
                        onChange={saveAlfa}
                        label="Επίπεδο: Α"
                        // disabled={betaIsTrue || gammaIsTrue || deltaIsTrue}
                    />
                    <AnswerSwitch
                        state={betaIsTrue}
                        // onChange={(newValue) => setBetaIsTrue(newValue)}
                        onChange={saveBeta}
                        label="Επίπεδο: Β"
                        // disabled={alfaIsTrue || gammaIsTrue || deltaIsTrue}
                    />
                    <AnswerSwitch
                        state={gammaIsTrue}
                        // onChange={(newValue) => setGammaIsTrue(newValue)}
                        onChange={saveGamma}
                        label="Επίπεδο: Γ"
                        // disabled={alfaIsTrue || betaIsTrue || deltaIsTrue}
                    />
                    <AnswerSwitch
                        state={deltaIsTrue}
                        // onChange={(newValue) => setDeltaIsTrue(newValue)}
                        onChange={saveDelta}
                        label="Επίπεδο: Δ"
                        // disabled={alfaIsTrue || betaIsTrue || gammaIsTrue}
                    />
                    <Line />
                </View>
            </View>
        </ScrollView>
        // </CustomLinearGradient>
    );
};

DifficultyLevelSettingsScreen.navigationOptions = ({ navigation }) => {
    return {
        headerTitle: navigation.getParam('userEmail'),
        headerLeft: (
            <HeaderButtons HeaderButtonComponent={CustomHeaderButton}>
                <Item
                    title="menu"
                    iconName={Platform.OS === 'android' ? 'md-menu' : 'ios-menu'}
                    onPress={() => navigation.toggleDrawer()}
                />
            </HeaderButtons>
        )

    };
};

还有一个包含 10 个开关的其他文件...

最佳答案

这个自定义钩子(Hook)就可以了

const useSaveQuestion = (saveFunc, deps) =>
    useCallback(
        newValue => {
            saveFunc(newValue);
            setDeleteFilters(true);
            setFiltersAreApplied(true);
        },
        [deleteFilters, filtersAreApplied, ...deps],
    );

这就是你如何使用它:

const saveAlfa = useSaveQuestion(
    newValue => {
        setAlfaIsTrue(newValue);
        saveQuestion();
    },
    [alfaIsTrue],
);

const saveBeta = useSaveQuestion(
    newValue => {
        setBetaIsTrue(newValue);
        saveQuestion();
    },
    [betaIsTrue],
);

关于javascript - 如何重构代码,使用一个函数代替 4 个函数,每个函数都使用特殊的 `useState` Hook (即 `setAlfaIsTrue(newValue)` ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59390375/

相关文章:

javascript - 大十六进制数的运算

javascript - 自动对焦后触发Jquery函数

javascript - 在嵌套组件中响应访问状态

javascript - React 使用 for 循环在每个 div 中追加 5 个项目

javascript - 在 Sencha Touch 中动态加载和初始化 Controller

javascript - 我应该在 JavaScript 中使用大 switch 语句而不会出现性能问题吗?

reactjs - React - 在呈现获取的数据之前显示加载消息

android - 在 React native Webview 中使用自定义字体

javascript - react native : Can't find variable: require

ios - 节点模块/react-native-vector-icons/lib/create-icon-set.js : #<WeakSet> could not be cloned