简体   繁体   English

将条件渲染移至单独的组件

[英]Move Conditional Rendering to a Separate Component

In my code, I take an input from the user, run a graphql query and then conditionally render some items according to the results (via showUsers functions).在我的代码中,我从用户那里获取输入,运行 graphql 查询,然后根据结果有条件地渲染一些项目(通过 showUsers 函数)。 However, instead of using showUsers here as a function, I want to make it a separate component where I can pass userData.但是,我不想在此处将 showUsers 用作 function,而是将其设为可以传递 userData 的单独组件。

export const AddContactTry: React.FunctionComponent = () => {
  const validationSchema = phoneNumberValidationSchema;

  const { values, handleChange, handleSubmit, dirty, handleBlur, isValid, resetForm, isSubmitting, setSubmitting, touched}= useFormik({
    initialValues: {
      phoneNumber: '',
    },
    validationSchema,
    onSubmit: (values: FormValues) => {
      handleSubmitForm(values);
    },
  });

  const [isSubmitted, setIsSubmitted] = useState(false);
  const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
  const navigation = useNavigation();
  //const validationSchema = phoneNumberValidationSchema;

  const [
    createUserRelationMutation,
    {
      data: addingContactData,
      loading: addingContactLoading,
      error: addingContactError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted: () => {
      Alert.alert('Contact Added');
    },
  });

  const showUsers = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        return (
          <View style={styles.users}>
            {data.users.nodes.map(
              (item: { firstName: string; lastName: string; id: number }) => {
                const userName = item.firstName
                  .concat(' ')
                  .concat(item.lastName);
                return (
                  <View style={styles.item} key={item.id}>
                    <Thumbnail
                      style={styles.thumbnail}
                      source={{
                        uri:
                          'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
                      }}></Thumbnail>
                    <Text style={styles.userName}>{userName}</Text>
                    <View style={styles.addButtonContainer}>
                      <Button
                        rounded
                        style={styles.addButton}
                        onPress={() => {
                          addContact(Number(item.id));
                          setIsSubmitted(false);
                          setUserData(null);
                        }}>
                        <Icon
                          name="plus"
                          size={moderateScale(20)}
                          color="black"
                        />
                      </Button>
                    </View>
                  </View>
                );
              },
            )}
          </View>
        );
      }
    },
    [createUserRelationMutation, userData],
  );

  const addContact = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
        },
      });
    },
    [createUserRelationMutation],
  );


  const getContactId = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      //resetForm();
      if (data) {
        if (data.users.nodes.length == 0) {
          Alert.alert('No User Found');
        } else {
          setUserData(data);
        }
      }
    },
    [addContact],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getContactId,
    onError: _onLoadUserError,
  });

  const handleSubmitForm = React.useCallback(
    (values: FormValues) => {
      setIsSubmitted(true);
      const plusSign = '+';
      const newPhoneNumber = plusSign.concat(values.phoneNumber);
      console.log('Submitted');
      loadUsers({
        variables: {
          where: { phoneNumber: newPhoneNumber },
        },
      });
      resetForm();
    },
    [loadUsers],
  );

  return (
    <SafeAreaView>
      <View style={styles.container}>
        <View style={styles.searchTopContainer}>
          <View>
                <View style={styles.searchFieldContainer}>
                  <View style={styles.form}>
                    <Item underline style={styles.newFieldInput} >
                      <Icon name="mobile" color="black" size={26}></Icon>
                     <Input 
                      onChangeText={handleChange('phoneNumber') as (text: string) => void}
                      onBlur={handleBlur('phoneNumber') as (event: any) => void}
                      value={values.phoneNumber}
                      placeholder="49152901820"
                    />
                    </Item>
                  </View>
                  <View style={styles.buttonContainer}>
                <Button
                  block
                  success
                  disabled={!isValid || !dirty}
                  onPress={handleSubmit}
                  style={styles.button}>
                  <Text>Speichern</Text>
                </Button>
                  </View>
                </View>
          </View>
          {isSubmitted && showUsers(userData)}
        </View>
      </View>
      {/* <User data={userData}></User> */}
    </SafeAreaView>
  );
};

Currently, the rendering happens here:目前,渲染发生在这里:

 {isSubmitted && showUsers(userData)}

Now, to move the rendering to a separate component, I tried to do this.现在,为了将渲染移至单独的组件,我尝试这样做。 Currently, this works:目前,这有效:

export const AddContactTry: React.FunctionComponent = () => {
  const validationSchema = phoneNumberValidationSchema;

  const { values, handleChange, handleSubmit, dirty, handleBlur, isValid, resetForm, isSubmitting, setSubmitting, touched}= useFormik({
    initialValues: {
      phoneNumber: '',
    },
    validationSchema,
    onSubmit: (values: FormValues) => {
      handleSubmitForm(values);
    },
  });

  const [isSubmitted, setIsSubmitted] = useState(false);
  const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
  const navigation = useNavigation();

  const _onLoadUserError = React.useCallback((error: ApolloError) => {
    Alert.alert('Oops, try again later');
  }, []);

  // const [
  //   createUserRelationMutation,
  //   {
  //     data: addingContactData,
  //     loading: addingContactLoading,
  //     error: addingContactError,
  //     called: isMutationCalled,
  //   },
  // ] = useCreateUserRelationMutation({
  //   onCompleted: () => {
  //     Alert.alert('Contact Added');
  //   },
  // });

  // const showUsers = React.useCallback(
  //   (data: UsersLazyQueryHookResult) => {
  //     if (data) {
  //       return (
  //         <View style={styles.users}>
  //           {data.users.nodes.map(
  //             (item: { firstName: string; lastName: string; id: number }) => {
  //               const userName = item.firstName
  //                 .concat(' ')
  //                 .concat(item.lastName);
  //               return (
  //                 <View style={styles.item} key={item.id}>
  //                   <Thumbnail
  //                     style={styles.thumbnail}
  //                     source={{
  //                       uri:
  //                         'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
  //                     }}></Thumbnail>
  //                   <Text style={styles.userName}>{userName}</Text>
  //                   <View style={styles.addButtonContainer}>
  //                     <Button
  //                       rounded
  //                       style={styles.addButton}
  //                       onPress={() => {
  //                         //addContact(Number(item.id));
  //                         setIsSubmitted(false);
  //                         setUserData(null);
  //                       }}>
  //                       <Icon
  //                         name="plus"
  //                         size={moderateScale(20)}
  //                         color="black"
  //                       />
  //                     </Button>
  //                   </View>
  //                 </View>
  //               );
  //             },
  //           )}
  //         </View>
  //       );
  //     }
  //   },
  //   [createUserRelationMutation, userData],
  // );

  // const addContact = React.useCallback(
  //   (id: Number) => {
  //     console.log('Whats the Id', id);
  //     createUserRelationMutation({
  //       variables: {
  //         input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
  //       },
  //     });
  //   },
  //   [createUserRelationMutation],
  // );

  const getContactId = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      //resetForm();
      if (data) {
        if (data.users.nodes.length == 0) {
          Alert.alert('No User Found');
        } else {
          setUserData(data);
        }
      }
    },
    //[addContact],
    [],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getContactId,
    onError: _onLoadUserError,
  });

  const handleSubmitForm = React.useCallback(
    (values: FormValues) => {
      setIsSubmitted(true);
      const plusSign = '+';
      const newPhoneNumber = plusSign.concat(values.phoneNumber);
      loadUsers({
        variables: {
          where: { phoneNumber: newPhoneNumber },
        },
      });
      resetForm();
    },
    [loadUsers],
  );

  // if (!addingContactLoading && isMutationCalled) {
  //   if (addingContactError) {
  //     Alert.alert('Unable to Add Contact');
  //   }
  // }

  return (
    <SafeAreaView>
      <View style={styles.container}>
        <View style={styles.searchTopContainer}>
          <View>
                <View style={styles.searchFieldContainer}>
                  <View style={styles.form}>
                    <Item underline style={styles.newFieldInput} >
                      <Icon name="mobile" color="black" size={26}></Icon>
                     <Input 
                      onChangeText={handleChange('phoneNumber') as (text: string) => void}
                      onBlur={handleBlur('phoneNumber') as (event: any) => void}
                      value={values.phoneNumber}
                      placeholder="49152901820"
                    />
                    </Item>
                  </View>
                  <View style={styles.buttonContainer}>
                <Button
                  block
                  success
                  disabled={!isValid || !dirty}
                  onPress={handleSubmit}
                  style={styles.button}>
                  <Text>Speichern</Text>
                </Button>
                  </View>
                </View>
          </View>
          {/* {isSubmitted && showUsers(userData)} */}
          <User data={userData}></User>
        </View>
      </View>
    </SafeAreaView>
  );
};
type UserProps = {
   data: UsersLazyQueryHookResult;
   //isSubmitted: boolean;
  };
  export const User: React.FunctionComponent<UserProps> = ({
    data,
    //isSubmitted,
  }) => {
console.log('user called');
    const [
      createUserRelationMutation,
      {
        data: addingContactData,
        loading: addingContactLoading,
        error: addingContactError,
        called: isMutationCalled,
      },
    ] = useCreateUserRelationMutation({
      onCompleted: () => {
        Alert.alert('Contact Added');
      },
    });

    const addContact = React.useCallback(
      (id: Number) => {
        console.log('Whats the Id', id);
        createUserRelationMutation({
          variables: {
            input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
          },
        });
      },
      [createUserRelationMutation],
    );

      if (!addingContactLoading && isMutationCalled) {
    if (addingContactError) {
      Alert.alert('Unable to Add Contact');
    }
  }
     //if (isSubmitted){
      if(!data) return null; 
    return (
        <View style={styles.users}>
          {data.users.nodes.map(
            (item: { firstName: string; lastName: string; id: number }) => {
              const userName = item.firstName
                .concat(' ')
                .concat(item.lastName);
              return (
                <View style={styles.item} key={item.id}>
                  <Thumbnail
                    style={styles.thumbnail}
                    source={{
                      uri:
                        'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
                    }}></Thumbnail>
                  <Text style={styles.userName}>{userName}</Text>
                  <View style={styles.addButtonContainer}>
                    <Button
                      rounded
                      style={styles.addButton}
                      onPress={() => {
                        addContact(Number(item.id));
                        //setIsSubmitted(false);
                        //setUserData(null);
                      }}>
                      <Icon
                        name="plus"
                        size={moderateScale(20)}
                        color="black"
                      />
                    </Button>
                  </View>
                </View>
              );
            },
          )}
        </View>
      );}

But I have commented out setIsSubmitted(false);但是我已经注释掉了setIsSubmitted(false); and setUserData(null);setUserData(null); in the User component.User组件中。 How can I pass them such that they'll be updated in the original screen too?我怎样才能通过它们以便它们也将在原始屏幕中更新?

Or is there a better way with which I can move out only the rendering list?还是有更好的方法可以只移出渲染列表?

Edit:编辑:

Trying this now but I get Cannot find name 'onAddContact'. Did you mean 'addContact'?现在尝试这个,但我Cannot find name 'onAddContact'. Did you mean 'addContact'? Cannot find name 'onAddContact'. Did you mean 'addContact'?

type UserProps = {
  data: UsersLazyQueryHookResult;
  onAddContact: any;
};
export const User: React.FunctionComponent<UserProps> = ({
  data,
  onAddContact,
  //isSubmitted,
}) => {
  console.log('user called');
  const [
    createUserRelationMutation,
    {
      data: addingContactData,
      loading: addingContactLoading,
      error: addingContactError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted: () => {
      Alert.alert('Contact Added');
    },
  });

  const addContact = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Contact, userId: 1 },
        },
      });
    },
    [createUserRelationMutation],
  );

  if (!addingContactLoading && isMutationCalled) {
    if (addingContactError) {
      Alert.alert('Unable to Add Contact');
    }
  }
  if (!data) return null;
  return (
    <View style={styles.users}>
      {data.users.nodes.map(
        (item: { firstName: string; lastName: string; id: number }) => {
          const userName = item.firstName.concat(' ').concat(item.lastName);
          return (
            <View style={styles.item} key={item.id}>
              <Thumbnail
                style={styles.thumbnail}
                source={{
                  uri:
                    'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
                }}></Thumbnail>
              <Text style={styles.userName}>{userName}</Text>
              <View style={styles.addButtonContainer}>
                <Button
                  rounded
                  style={styles.addButton}
                  onPress={() => onAddContact(Number(item.id))}
                  // onPress={() => {
                  //   addContact(Number(item.id));
                  // }}
                  >
                  <Icon name="plus" size={moderateScale(20)} color="black" />
                </Button>
              </View>
            </View>
          );
        },
      )}
    </View>
  );
};
<User onAddContact={onAddContact} data={userData}></User>

Could you try the following?你能试试下面的吗?

{isSubmitted && userData && userData.users && userData.users.nodes ? <User data={userData}/> : null}

Ideally you would destruct data.users.nodes理想情况下,您会破坏data.users.nodes

const { data: {users: {nodes: userNodes} = {} } = {} } = userData || {};

and pass just an array并只传递一个数组

{isSubmitted && userNodes ? <User data={userNodes}/> : null}

--Edit - 编辑

Delegate action to parent as User is presentational component将操作委托给父级,因为User是表示组件

 export const User: React.FunctionComponent<UserProps> = ({
    data,
    onAddContact,
  }) => {

onPress={() => onAddContact(Number(item.id))}
const onAddContact = (id: number) => {
  setIsSubmitted(false);
  setUserData(null);
  createUserRelationMutation({
    variables: {
      input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
    },
  });
}

<User onAddContact={onAddContact} data={userData}></User>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM