我通常会尝试自己解决问题,因此我可以通过检查StackOverflow和Google来从中学到更多,但这已经让我陷入了太久了...
因此,我正在创建一个React-Native应用程序(没有Expo),并使用redux,redux-thunk和react-redux。
有一项功能,使已登录的用户能够输入或编辑他/她对将来日期的可用性。 因此,我有适当的虚拟数据来设置初始值。
我可以成功地编辑任何日期(使用Availability-day.component.tsx),并在用户配置文件屏幕(profile.component.tsx)上显示更新的可用性。
但是,当我尝试在第一次编辑后再编辑其他任何日期时,它将运行我的代码直到相应的redux动作代码的结尾,但不会执行相应的redux reducer代码(尽管它确实运行了该代码)第一次编辑)...
#TLDR 我可以编辑和更新一次现有的可用性,但是reducer代码不会在连续编辑的情况下执行
有什么想法会导致这种情况以及如何解决?
#FILES
Relevant Files on Google Drive
由于字符限制,我无法在下面的问题或评论中添加所有文件,因此将它们存储在Google云端硬盘中。
// reducer action snippet
export const updateAvailability = (
userId,
userAccountType,
userFirstName,
userLastName,
userEmail,
userPhoneNumber,
userAvatar,
userAddress,
userLocation,
userBio,
userFollowers,
userFollowing,
userPosts,
updatedUserAvailability,
userGender,
userAge,
) => {
return async (dispatch) => {
const date = new Date();
console.log('ARRIVED AT START OF USERS ACTIONS');
console.log(updatedUserAvailability);
try {
dispatch({
type: UPDATE_AVAILABILITY,
profileData: {
userId: userId,
userAccountType: userAccountType,
userFirstName: userFirstName,
userLastName: userLastName,
userEmail: userEmail,
userPhoneNumber: userPhoneNumber,
userAvatar: userAvatar,
userAddress: userAddress,
userLocation: userLocation,
userBio: userBio,
userFollowers: userFollowers,
userFollowing: userFollowing,
userPosts: userPosts,
userAvailability: updatedUserAvailability,
userGender: userGender,
userAge: userAge,
},
});
} catch (err) {
// send to custom analytics server
throw err;
}
};
};
// redux reducer snippet
import {
GET_PROFILES,
CREATE_PROFILE,
UPDATE_PROFILE,
UPDATE_AVAILABILITY,
} from '../actions/users';
const initialState = {
availableProfiles: PROFILES,
activeProfile: PROFILES.find((profile) => profile.userId === 'u2'),
error: null,
};
const usersReducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_AVAILABILITY:
console.log('ARRIVED AT START REDUCER');
// Find and update the activeUser Profile.
const updatingProfileIndex = state.availableProfiles.findIndex(
(profile) => profile.userId === action.profileData.userId,
);
console.log(updatingProfileIndex);
console.log(action.profileData.userAvailability);
const updatedAvailabilityProfile = new Profile(
action.profileData.userId,
action.profileData.userAccountType,
action.profileData.userFirstName,
action.profileData.userLastName,
action.profileData.userEmail,
action.profileData.userPhoneNumber,
action.profileData.userAvatar,
action.profileData.userAddress,
action.profileData.userLocation,
action.profileData.userBio,
action.profileData.userFollowers,
action.profileData.userFollowing,
action.profileData.userPosts,
action.profileData.userAvailability,
action.profileData.userGender,
action.profileData.userAge,
);
console.log(updatedAvailabilityProfile);
console.log(
'UPDATED AVAILABILITIY PROFILE=' +
JSON.stringify(updatedAvailabilityProfile),
);
// const updatedActiveProfile = [...state.activeProfile];
// console.log(updatedActiveProfile);
// updatedActiveProfile[profileIndex] = updatedProfile;
// console.log(updatedActiveProfile);
// Update the activeUser Profile in the availableProfiles array.
const updatingAvailableProfiles = {...state.availableProfiles};
updatingAvailableProfiles[
updatingProfileIndex
] = updatedAvailabilityProfile;
// Return the updated profile states
return {
...state,
availableProfiles: updatingAvailableProfiles,
activeProfile: updatedAvailabilityProfile,
};
default:
return state;
}
};
export default usersReducer;
// editing component that sends updated values to redux
import React from 'react';
import {View} from 'react-native';
import {
Avatar,
Button,
StyleService,
Text,
TopNavigation,
TopNavigationAction,
useStyleSheet,
useTheme,
Modal,
Card,
Datepicker,
Spinner,
} from '@ui-kitten/components';
import * as usersActions from '../../store/actions/users';
import {Availability, Profile} from '../../data/profile.model';
import {brandingAppIcon} from '../../assets/images/branding';
import {Timepicker} from '../../components/UI/time-picker.component';
import {AvailabilityDayEditScreenProps} from '../../navigation/profile.navigator';
import {useSelector, connect, useDispatch} from 'react-redux';
import {AppRoute} from '../../navigation/app-routes';
export type AvailabilityDayEditRouteParams = {
editableAvailability: number;
};
export const AvailabilityDayEditScreen = (
props: AvailabilityDayEditScreenProps,
): SafeAreaLayoutElement => {
const {editableAvailability} = props.route.params;
console.log(editableAvailability);
const currentUser: Profile = useSelector(
(state) => state.users.activeProfile,
);
console.log(currentUser);
const [isLoading, setIsLoading] = React.useState(false);
const [error, setError] = React.useState();
const [activeUser, setActiveUser] = React.useState<Profile>(currentUser);
const [userAvailability, setUserAvailability] = React.useState<
Availability[]
>(activeUser.userAvailability);
const [userAvailabilityEditing, setUserAvailabilityEditing] = React.useState<
Object
>(activeUser.userAvailability[editableAvailability]);
const [editDate, setEditDate] = React.useState<Date>(
userAvailabilityEditing.date,
);
const [editDateFrom, setEditDateFrom] = React.useState<Date>(
userAvailabilityEditing.from,
);
const [editDateTo, setEditDateTo] = React.useState<Date>(
userAvailabilityEditing.to,
);
React.useEffect(() => {
setActiveUser(currentUser);
setUserAvailability(currentUser.userAvailability);
}, [currentUser]);
const dispatch = useDispatch();
const submitHandler = React.useCallback(async () => {
// if (!formState.formIsValid) {
// Alert.alert('Wrong input!', 'Please check the errors in the form.', [
// {text: 'OK'},
// ]);
// return;
// }
setError(null);
setIsLoading(true);
try {
console.log(userAvailabilityEditing);
// console.log('EDITDATE=' + editDate);
// console.log('EDITFROM=' + editDateFrom);
// console.log('EDITTO=' + editDateTo);
const newUserAvailabilityEditing = {
...userAvailabilityEditing,
from: editDateFrom,
to: editDateTo,
};
console.log(newUserAvailabilityEditing); // CORRECT
// setEditDate(undefined); // reset editDate
const updatedUserAvailability = userAvailability.map((availItem) => {
if (userAvailability.indexOf(availItem) === editableAvailability) {
return newUserAvailabilityEditing;
}
return availItem;
});
console.log('UPDATED USER AVAILABILITY BELOW');
console.log(updatedUserAvailability); // CORRECT
// console.log(activeUser);
if (activeUser) {
await dispatch(
usersActions.updateAvailability(
activeUser.userId,
activeUser.userAccountType,
activeUser.userFirstName,
activeUser.userLastName,
activeUser.userEmail,
activeUser.userPhoneNumber,
activeUser.userAvatar,
activeUser.userAddress,
activeUser.userLocation,
activeUser.userBio,
activeUser.userFollowers,
activeUser.userFollowing,
activeUser.userPosts,
updatedUserAvailability,
activeUser.userGender,
activeUser.userAge,
),
);
}
} catch (err) {
setError(err.message);
}
setIsLoading(false);
console.log('Sending User Back to Profile Screen');
props.navigation.navigate(AppRoute.PROFILE);
}, [
props.navigation,
userAvailabilityEditing,
editDateFrom,
editDateTo,
userAvailability,
activeUser,
editableAvailability,
dispatch,
]);
if (isLoading) {
return (
<View style={styles.centeredLoader}>
<Spinner size="large" />
</View>
);
}
return (
<Card
disabled={true}
style={styles.container}
header={() => (
<View>
<Avatar style={styles.profileAvatar} source={brandingAppIcon} />
</View>
)}>
<Text>Please edit your availability for this date.</Text>
<View style={styles.availabilityDayEdit}>
<Datepicker date={editDate} disabled />
<Timepicker
key={'editStartTime'}
placeholder="Available to start at"
date={editDateFrom}
onSelect={(nextTime) => {
setEditDateFrom(nextTime);
}}
/>
<Timepicker
key={'editEndTime'}
placeholder="Available until"
date={editDateTo}
onSelect={(nextTime) => {
setEditDateTo(nextTime);
}}
/>
</View>
<Text>{error}</Text>
<Button onPress={submitHandler}>UPDATE AVAILABILITY</Button>
</Card>
);
};
const styles = StyleService.create({
safeArea: {
flex: 1,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
// backgroundColor: 'background-basic-color-2',
},
appName: {
color: 'text-control-color',
},
header: {
flex: 1,
paddingVertical: 24,
alignItems: 'center',
justifyContent: 'center',
},
profileAvatar: {
width: 124,
height: 124,
alignSelf: 'center',
borderRadius: 62,
marginVertical: 16,
},
profileName: {
zIndex: 1,
},
locationContainer: {
flexDirection: 'row',
alignItems: 'center',
},
location: {
marginVertical: 8,
},
profileButtonsContainer: {
flexDirection: 'row',
marginVertical: 32,
marginHorizontal: 20,
},
profileButton: {
flex: 1,
marginHorizontal: 4,
},
socialsContainer: {
flexDirection: 'row',
width: '75%',
marginVertical: 8,
},
profileSocial: {
flex: 1,
alignSelf: 'center',
},
sectionLabel: {
marginTop: 16,
marginBottom: 8,
marginHorizontal: 16,
},
profileDescription: {
marginHorizontal: 16,
},
friendsList: {
marginHorizontal: 8,
},
friendItem: {
alignItems: 'center',
marginHorizontal: 8,
},
friendName: {
marginTop: 8,
},
postItem: {
flex: 1,
aspectRatio: 1.0,
},
availabilityContainer: {
marginLeft: 16,
marginRight: -16,
},
availabilityItemLabel: {
flex: 1,
textDecorationLine: 'underline',
},
availabilityItemValue: {
flex: 1,
},
availabilityItem: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
marginVertical: 8,
},
availabilityItemDate: {
flex: 3,
},
availabilityItemTime: {
flex: 1,
},
availabilityItemButton: {
// flex: 1,
marginRight: 30,
},
addVenueItem: {
marginHorizontal: 8,
alignItems: 'center',
marginLeft: 0,
},
addVenueButton: {
aspectRatio: 1.0,
height: 42,
borderRadius: 24,
color: 'text-control-color',
paddingRight: 7,
// resizeMode: 'contain',
// width: 50,
// height: 50,
// borderRadius: 50,
// backgroundColor:'black'
},
addVenueButtonText: {
paddingTop: 5,
fontSize: 13,
},
modalBackdrop: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
availabilityDayEdit: {
flexDirection: 'row',
paddingVertical: 16,
justifyContent: 'space-between',
},
});
connect()(AvailabilityDayEditScreen);
答案 0 :(得分:0)
和小家伙一起散步回来后,我终于想通了,并想与遇到这个问题的任何人分享错误的原因...:)
我正在尝试创建一个重复的可变状态数组,并最终得到以下一行:
const updatingAvailableProfiles = {...state.availableProfiles};
将其设置回
后const updatingAvailableProfiles = state.availableProfiles;
它再次按预期工作。