所以我想重构下面的代码,这样我就不必一次又一次地重复它。
我做了一个函数 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/