我已经编写了用于在我的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()}
</>
);
}
};
答案 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>
);
}