在react-native上使用钩子

时间:2020-04-09 12:19:58

标签: react-native

我已经编写了用于在我的Expo应用程序上处理多个图像选择的钩子。

import { useCallback, useState } from 'react';
import { CameraRoll } from 'react-native';

export function useCameraRoll({
  first = 40,
  assetType = 'Photos',
  groupTypes = 'All',
}) {
  const [photos, setPhotos] = useState([]);
  const [after, setAfter] = useState(null);
  const [hasNextPage, setHasNextPage] = useState(true);

  const getPhotos = useCallback(async () => {
    if (!hasNextPage) return;

    const { edges, page_info: pageInfo } = await CameraRoll.getPhotos({
      first,
      assetType,
      groupTypes,
      ...(after && { after }),
    });

    if (after === pageInfo.end_cursor) return;

    const images = edges.map(i => i.node).map(i => i.image);

    setPhotos([...photos, ...images]);
    setAfter(pageInfo.end_cursor);
    setHasNextPage(pageInfo.has_next_page);
  }, [after, hasNextPage, photos]);

  return [photos, getPhotos];
}

我在另一个组件上引用钩子函数,如下所示:

import { useCameraRoll } from '../shared/hooks';

 const _pickImage = async () => {
    const [photos, getPhotos] = await useCameraRoll({first: 80})
  };

并启动要在onPress上运行的功能:

<TouchableOpacity style={styles.button} onPress={_pickImage}>
        <Text style={{ color: 'white' }}>Add Photos</Text>
      </TouchableOpacity>

但是我得到了:无效的挂接调用。挂钩只能在功能组件的主体内部调用。

我错过了什么吗?请告知。

谢谢。

更新的代码:

        const RenderImagePicker = ({
  // eslint-disable-next-line no-unused-vars
  setFieldValue,
  name,
  value,
  label,
  meta: { touched, error },
}) => {
  const [uploading, setUploading] = useState(false);
  function MyComponent() {
    const [photos, getPhotos] = useCameraRoll({ first: 80 });
  }
  return (
    <TouchableOpacity style={styles.button} onPress={MyComponent}>
      <Text style={{ color: "white" }}>Add Photos</Text>
    </TouchableOpacity>
  );
};


  const _handleImagePicked = async (pickerResult) => {
    try {
      setUploading(true);
      if (!pickerResult.cancelled) {
        const uploadResponse = await uploadImageAsync(pickerResult.uri);
        const uploadResult = await uploadResponse.json();
        setFieldValue(name, uploadResult.location);
      }
    } catch (e) {
      console.log(e);
      // eslint-disable-next-line no-undef
      alert('Upload failed, sorry :(');
    } finally {
      setUploading(false);
    }
    async function uploadImageAsync(uri) {
      const apiUrl = 'http://xx:3000/upload';
      const uriParts = uri.split('.');
      const fileType = uriParts[uriParts.length - 1];

      // eslint-disable-next-line no-undef
      const formData = new FormData();
      formData.append('photo', {
        uri,
        name: `photo.${fileType}`,
        type: `image/${fileType}`,
      });

      const options = {
        method: 'POST',
        body: formData,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
        },
      };
      console.log(options);
      return fetch(apiUrl, options);
    }
  };



  const _maybeRenderUploadingOverlay = () => {
    if (uploading) {
      return (
        <View>
          <ActivityIndicator
            color="#ff0000"
            size="large"
            style={{ alignSelf: 'center', flex: 1 }}
          />
        </View>
      );
    }
  };


  function MyComponent() {
    const [photos, getPhotos] = useCameraRoll({first: 80});
    return (
      <>
        <TouchableOpacity style={styles.button} onPress={getPhotos}>    
        <Text style={{ color: 'white' }}>Add Photos</Text>  
      </TouchableOpacity>
        {!!error && <Text style={{ color: 'red' }}>{error}</Text>}
        {_maybeRenderUploadingOverlay()}
      </>
    );
  }
};

1 个答案:

答案 0 :(得分:1)

正如Rules of Hooks中明确提到的那样,只能在功能组件的顶层中调用钩子。不是在循环,嵌套函数,条件(也包括其他钩子主体)内部。您可以如下所示修改代码:

import { useCameraRoll } from '../shared/hooks';

function MyComponent() {
    const [photos, getPhotos] = await useCameraRoll({first: 80});

    return (
      <TouchableOpacity style={styles.button} onPress={getPhotos}>
        <Text style={{ color: 'white' }}>Add Photos</Text>
      </TouchableOpacity>
     );
}