在循环内渲染和 return
Render and return inside a loop
在我的代码中,我调用了一个函数showUsers
。此函数在样式框中显示所有用户。现在,传递给它的 numberOfUsers
是 1,console.logs 也证实了这一点。
所以循环应该只运行一次。但是,所有这些 console.logs 都重复了两次。输出值保持不变。为什么会这样?
console.log('Number of Users in Loop: ', numberOfUsers);
console.log('Whats the Id', userId);
console.log('UserName', userName);
console.log('i: ', i);
代码:
export const Page: React.FunctionComponent<PageProps> = ({
toggleShowPage,
showAddFriendEmailPage,
}) => {
const initialValues: FormValues = {
email: '',
};
const [errorMessage, setErrorMessage] = useState('');
const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
const [numberOfUsers, setNumberOfUsers] = useState('');
const validationSchema = emailValidationSchema;
useEffect(() => {
setUserData(userData);
setNumberOfUsers(numberOfUsers);
}, [userData, numberOfUsers]);
const showAlert = () => {
Alert.alert('Friend Added');
};
useEffect(() => {
if (showAddFriendEmailPage) return;
initialValues.email = '';
}, [showAddFriendEmailPage]);
const _onLoadUserError = React.useCallback((error: ApolloError) => {
setErrorMessage(error.message);
Alert.alert('Unable to Add Friend');
}, []);
const [
createUserRelationMutation,
{
data: addingFriendData,
loading: addingFriendLoading,
error: addingFriendError,
called: isMutationCalled,
},
] = useCreateUserRelationMutation({
onCompleted: (data: CreateUserRelationMutationResult) => {
showAlert();
},
});
const showUsers = React.useCallback(
(data: UsersLazyQueryHookResult, numberOfUsers: Number) => {
for (var i = 0; i < numberOfUsers; i++) {
console.log('Number of Users in Loop: ', numberOfUsers);
const userId = data.users.nodes[i].id;
const userName = ((data.users.nodes[i].firstName).concat(' ')).concat(data.users.nodes[i].lastName);
console.log('Whats the Id', userId);
console.log('UserName', userName);
console.log('Loop');
return(
<View style={styles.friends}>
<View style={styles.item}>
<Text>{userName}</Text>
</View>
</View>
)
}
},
[createUserRelationMutation],
);
const addFriend = React.useCallback(
(id: Number) => {
console.log('Whats the Id', id);
createUserRelationMutation({
variables: {
input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
},
});
},
[createUserRelationMutation],
);
const getFriendId = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
if (data.users.nodes.length == 0) {
setErrorMessage('User Not Found');
Alert.alert('User Not Found');
} else {
setUserData(data);
setNumberOfUsers(data.users.nodes.length);
//showUsers(data, Number(numberOfUsers));
addFriend(Number(data.users.nodes[0].id));
}
}
},
[addFriend],
);
const [loadUsers] = useUsersLazyQuery({
onCompleted: getFriendId,
onError: _onLoadUserError,
});
const handleSubmitForm = React.useCallback(
(values: FormValues, helpers: FormikHelpers<FormValues>) => {
console.log('Submitted');
loadUsers({
variables: {
where: { email: values.email },
},
});
values.email = '';
},
[loadUsers],
);
return (
<Modal
visible={showAddFriendEmailPage}
animationType="slide"
transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.email}
fieldType="email"
/>
<ErrorMessage
name="email"
render={msg => (
<Text style={styles.errorText}>{msg}</Text>
)}
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={handleSubmit}>
<Text style={styles.text}>Add Friend </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{showUsers(userData, Number(numberOfUsers))}
</View>
</View>
</SafeAreaView>
</Modal>
);
};
更新代码:
export const Page: React.FunctionComponent<PageProps> = ({
toggleShowPage,
showAddFriendEmailPage,
}) => {
const initialValues: FormValues = {
email: '',
};
const [errorMessage, setErrorMessage] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false);
const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
const [numberOfUsers, setNumberOfUsers] = useState('');
const validationSchema = emailValidationSchema;
const showUsers = React.useCallback(
(data: UsersLazyQueryHookResult, numberOfUsers: Number) => {
if (data){
for (var i = 0; i < numberOfUsers; i++) {
console.log('Number of Users in Loop: ', numberOfUsers);
const userId = data.users.nodes[i].id;
const userName = data.users.nodes[i].firstName
.concat(' ')
.concat(data.users.nodes[i].lastName);
return (
<View style={styles.friends}>
<View style={styles.item}>
<Text style={styles.userName}>{userName}</Text>
<View style={styles.addButtonContainer}>
<Button
onPress={() => {
addFriend(Number(data.users.nodes[i].id));
setIsSubmitted(false);
}}>
</Button>
</View>
</View>
</View>
);
}}
},
[createUserRelationMutation, userData, numberOfUsers],
);
const addFriend = React.useCallback(
(id: Number) => {
console.log('Whats the Id', id);
createUserRelationMutation({
variables: {
input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
},
});
},
[createUserRelationMutation],
);
const getFriendId = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
if (data.users.nodes.length == 0) {
setErrorMessage('User Not Found');
Alert.alert('User Not Found');
} else {
setUserData(data);
setNumberOfUsers(data.users.nodes.length);
}
}
},
[addFriend],
);
const [loadUsers] = useUsersLazyQuery({
onCompleted: getFriendId,
onError: _onLoadUserError,
});
const handleSubmitForm = React.useCallback(
(values: FormValues, helpers: FormikHelpers<FormValues>) => {
setIsSubmitted(true);
console.log('Submitted');
loadUsers({
variables: {
where: { email: values.email },
},
});
values.email = '';
},
[loadUsers],
);
if (!addingFriendLoading && isMutationCalled) {
if (addingFriendError) {
setErrorMessage(addingFriendError.message);
Alert.alert('Unable to Add Friend');
}
}
return (
<Modal
visible={showAddFriendEmailPage}
animationType="slide"
transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<View style={styles.searchTopTextContainer}>
<Text
style={styles.searchCancelDoneText}
onPress={() => {
toggleShowPage()
setIsSubmitted(false);
setUserData(null);
}}
>
Cancel
</Text>
<Text style={styles.searchTopMiddleText}>
Add Friend by Email
</Text>
<Text style={styles.searchCancelDoneText}>Done</Text>
</View>
<View>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.email}
fieldType="email"
/>
<ErrorMessage
name="email"
render={msg => (
<Text style={styles.errorText}>{msg}</Text>
)}
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={handleSubmit}>
<Text style={styles.text}>Search </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{isSubmitted && showUsers(userData, Number(numberOfUsers))}
</View>
</View>
</SafeAreaView>
</Modal>
);
};
您还从 getFriendId
调用 setUserData
,因此它将更新 userData
const getFriendId = React.useCallback(
....
setUserData(data);
因此它将调用 render
和 useEffect
useEffect(() => {
setUserData(userData);
setNumberOfUsers(numberOfUsers);
}, [userData, numberOfUsers]);
你可以注释掉useEffect
并勾选console.log
在我的代码中,我调用了一个函数showUsers
。此函数在样式框中显示所有用户。现在,传递给它的 numberOfUsers
是 1,console.logs 也证实了这一点。
所以循环应该只运行一次。但是,所有这些 console.logs 都重复了两次。输出值保持不变。为什么会这样?
console.log('Number of Users in Loop: ', numberOfUsers);
console.log('Whats the Id', userId);
console.log('UserName', userName);
console.log('i: ', i);
代码:
export const Page: React.FunctionComponent<PageProps> = ({
toggleShowPage,
showAddFriendEmailPage,
}) => {
const initialValues: FormValues = {
email: '',
};
const [errorMessage, setErrorMessage] = useState('');
const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
const [numberOfUsers, setNumberOfUsers] = useState('');
const validationSchema = emailValidationSchema;
useEffect(() => {
setUserData(userData);
setNumberOfUsers(numberOfUsers);
}, [userData, numberOfUsers]);
const showAlert = () => {
Alert.alert('Friend Added');
};
useEffect(() => {
if (showAddFriendEmailPage) return;
initialValues.email = '';
}, [showAddFriendEmailPage]);
const _onLoadUserError = React.useCallback((error: ApolloError) => {
setErrorMessage(error.message);
Alert.alert('Unable to Add Friend');
}, []);
const [
createUserRelationMutation,
{
data: addingFriendData,
loading: addingFriendLoading,
error: addingFriendError,
called: isMutationCalled,
},
] = useCreateUserRelationMutation({
onCompleted: (data: CreateUserRelationMutationResult) => {
showAlert();
},
});
const showUsers = React.useCallback(
(data: UsersLazyQueryHookResult, numberOfUsers: Number) => {
for (var i = 0; i < numberOfUsers; i++) {
console.log('Number of Users in Loop: ', numberOfUsers);
const userId = data.users.nodes[i].id;
const userName = ((data.users.nodes[i].firstName).concat(' ')).concat(data.users.nodes[i].lastName);
console.log('Whats the Id', userId);
console.log('UserName', userName);
console.log('Loop');
return(
<View style={styles.friends}>
<View style={styles.item}>
<Text>{userName}</Text>
</View>
</View>
)
}
},
[createUserRelationMutation],
);
const addFriend = React.useCallback(
(id: Number) => {
console.log('Whats the Id', id);
createUserRelationMutation({
variables: {
input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
},
});
},
[createUserRelationMutation],
);
const getFriendId = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
if (data.users.nodes.length == 0) {
setErrorMessage('User Not Found');
Alert.alert('User Not Found');
} else {
setUserData(data);
setNumberOfUsers(data.users.nodes.length);
//showUsers(data, Number(numberOfUsers));
addFriend(Number(data.users.nodes[0].id));
}
}
},
[addFriend],
);
const [loadUsers] = useUsersLazyQuery({
onCompleted: getFriendId,
onError: _onLoadUserError,
});
const handleSubmitForm = React.useCallback(
(values: FormValues, helpers: FormikHelpers<FormValues>) => {
console.log('Submitted');
loadUsers({
variables: {
where: { email: values.email },
},
});
values.email = '';
},
[loadUsers],
);
return (
<Modal
visible={showAddFriendEmailPage}
animationType="slide"
transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.email}
fieldType="email"
/>
<ErrorMessage
name="email"
render={msg => (
<Text style={styles.errorText}>{msg}</Text>
)}
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={handleSubmit}>
<Text style={styles.text}>Add Friend </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{showUsers(userData, Number(numberOfUsers))}
</View>
</View>
</SafeAreaView>
</Modal>
);
};
更新代码:
export const Page: React.FunctionComponent<PageProps> = ({
toggleShowPage,
showAddFriendEmailPage,
}) => {
const initialValues: FormValues = {
email: '',
};
const [errorMessage, setErrorMessage] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false);
const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
const [numberOfUsers, setNumberOfUsers] = useState('');
const validationSchema = emailValidationSchema;
const showUsers = React.useCallback(
(data: UsersLazyQueryHookResult, numberOfUsers: Number) => {
if (data){
for (var i = 0; i < numberOfUsers; i++) {
console.log('Number of Users in Loop: ', numberOfUsers);
const userId = data.users.nodes[i].id;
const userName = data.users.nodes[i].firstName
.concat(' ')
.concat(data.users.nodes[i].lastName);
return (
<View style={styles.friends}>
<View style={styles.item}>
<Text style={styles.userName}>{userName}</Text>
<View style={styles.addButtonContainer}>
<Button
onPress={() => {
addFriend(Number(data.users.nodes[i].id));
setIsSubmitted(false);
}}>
</Button>
</View>
</View>
</View>
);
}}
},
[createUserRelationMutation, userData, numberOfUsers],
);
const addFriend = React.useCallback(
(id: Number) => {
console.log('Whats the Id', id);
createUserRelationMutation({
variables: {
input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
},
});
},
[createUserRelationMutation],
);
const getFriendId = React.useCallback(
(data: UsersLazyQueryHookResult) => {
if (data) {
if (data.users.nodes.length == 0) {
setErrorMessage('User Not Found');
Alert.alert('User Not Found');
} else {
setUserData(data);
setNumberOfUsers(data.users.nodes.length);
}
}
},
[addFriend],
);
const [loadUsers] = useUsersLazyQuery({
onCompleted: getFriendId,
onError: _onLoadUserError,
});
const handleSubmitForm = React.useCallback(
(values: FormValues, helpers: FormikHelpers<FormValues>) => {
setIsSubmitted(true);
console.log('Submitted');
loadUsers({
variables: {
where: { email: values.email },
},
});
values.email = '';
},
[loadUsers],
);
if (!addingFriendLoading && isMutationCalled) {
if (addingFriendError) {
setErrorMessage(addingFriendError.message);
Alert.alert('Unable to Add Friend');
}
}
return (
<Modal
visible={showAddFriendEmailPage}
animationType="slide"
transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<View style={styles.searchTopTextContainer}>
<Text
style={styles.searchCancelDoneText}
onPress={() => {
toggleShowPage()
setIsSubmitted(false);
setUserData(null);
}}
>
Cancel
</Text>
<Text style={styles.searchTopMiddleText}>
Add Friend by Email
</Text>
<Text style={styles.searchCancelDoneText}>Done</Text>
</View>
<View>
<Formik
initialValues={initialValues}
onSubmit={handleSubmitForm}
validationSchema={validationSchema}>
{({ handleChange, handleBlur, handleSubmit, values }) => (
<View style={styles.searchFieldContainer}>
<View style={styles.form}>
<FieldInput
handleChange={handleChange}
handleBlur={handleBlur}
value={values.email}
fieldType="email"
/>
<ErrorMessage
name="email"
render={msg => (
<Text style={styles.errorText}>{msg}</Text>
)}
/>
</View>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={handleSubmit}>
<Text style={styles.text}>Search </Text>
</Button>
</View>
</View>
)}
</Formik>
</View>
{isSubmitted && showUsers(userData, Number(numberOfUsers))}
</View>
</View>
</SafeAreaView>
</Modal>
);
};
您还从 getFriendId
调用 setUserData
,因此它将更新 userData
const getFriendId = React.useCallback(
....
setUserData(data);
因此它将调用 render
和 useEffect
useEffect(() => {
setUserData(userData);
setNumberOfUsers(numberOfUsers);
}, [userData, numberOfUsers]);
你可以注释掉useEffect
并勾选console.log