Oliver Darby
Oliver Darby

Reputation: 544

How to simplify an error callback in react

I have a parent component that handles an error callback from its child components however in keeping with do not repeat yourself there seems to be a lot of repitition in my code id like to eliminate.

    function BasicInfo() {
    const {shell, ageAndGender, body} = styles;
    const {dispatch, state: {firstname}} = useSignUpState();
    const [firstnameError, setFirstnameError] = useState(true);
    const [ageError, setAgeError] = useState(true);
    const [genderError, setGenderError] = useState(true);
    const [sexualOrientationError, setSexualOrientationError] = useState(true);
    const [heightError, setHeightError] = useState(true);

    const setUserAgeError = useCallback(val => {
        setAgeError(val);
    }, [setAgeError]);

    const setUserGenderError = useCallback(val => {
        setGenderError(val);
    }, [setGenderError]);

    const setUserSexualOrientationError = useCallback(val => {
        setSexualOrientationError(val);
    }, [setSexualOrientationError]);

    const setUserHeightError = useCallback(val => {
        setHeightError(val);
    }, [setHeightError]);

    const handleError = () => {
        return firstnameError || ageError || sexualOrientationError || genderError || heightError;
    }

    useEffect(() => {
        if (firstname === '') {
            setFirstnameError(true);
        } else setFirstnameError(false);
    }, [firstname])

    return (
        <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
            <View style={shell}>
                <View style={{flex: 10}}>
                    <SignUpHeader title={`Enter a bit about\nyourself`} page={1}/>
                    <View style={body}>
                        <TextInput
                            autoComplete
                            mode="outlined"
                            label="Firstname"
                            value={firstname}
                            onChangeText={firstname => dispatch(setFirstname(firstname))}
                            style={{maxHeight: 64, marginBottom: 32}}
                            activeOutlineColor={"#000"}
                            outlineColor={"#DBDBDB"}
                            theme={{
                                colors: {
                                    text: "#000",
                                    placeholder: "#878787",
                                    background: "#FFF"
                                }
                            }}
                        />
                        <View style={ageAndGender}>
                            <AgeButton setBasicInfoError={setUserAgeError}/>
                            <GenderButton setBasicInfoError={setUserGenderError}/>
                        </View>
                        <SexualOrientationButton setBasicInfoError={setUserSexualOrientationError}/>
                        <HeightButton setBasicInfoError={setUserHeightError}/>
                    </View>
                </View>
                <SignUpFooter
                    buttonTitle="Next"
                    disabled={handleError()}
                    route="BasicInfo"
                    title={`Basic\nInfo`}
                />
            </View>
        </TouchableWithoutFeedback>
    );
}

As you can see in the code above every error is passed down to its child, does something very similar to my firstname useEffect which checks if its not valid and sets a boolean which is then checked by the parent. Is there a way to maybe create just one callback as say an array and say if length is > 1 set the error? Any help with this would be great to avoid duplication! Thanks

Upvotes: 0

Views: 602

Answers (1)

RadicalTurnip
RadicalTurnip

Reputation: 131

This looks like something you need to condense into a single useState. If you only expect one error at a time (even if they can be fairly close together) then you can simply have

[error, useError] = useState("");

And then set the error to "age" or "gender". In UseEffect, you use a switch to handle all possible use cases.

If you want multiple errors handled at a time, it looks pretty similar, but your useState starts out looking more like this

[error, useError] = useState({
age: true, gender: true, sexualOrientation: true, height: true
})

Again, with this method, you can use a single useEffect to monitor it. To handle changing a single piece, you can use the spread operator

useError({...error, age: false})

which changes age to false, but keeps everything else the same.

Upvotes: 1

Related Questions