expo convert from class to function - reactjs

I am converting this code, which is working fine, from class to function. Replaced all of the classes to functions, created constant and useState as per many examples I have seen. There is no errors but it is not working and I can't figure out what is wrong. Any help is appreciated.
class App extends Component {
state = {
image: null,
uploading: false,
};
render() {
let {
image
} = this.state;
return (
...
);
}
_takePhoto = async () => {
const {
status: cameraPerm
} = await Permissions.askAsync(Permissions.CAMERA);
const {
status: cameraRollPerm
} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
// only if user allows permission to camera AND camera roll
if (cameraPerm === 'granted' && cameraRollPerm === 'granted') {
let pickerResult = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [4, 3],
quality: 0.2,
});
this._handleImagePicked(pickerResult);
}
};
_handleImagePicked = async pickerResult => {
let uploadResponse, uploadResult;
try {
this.setState({
uploading: true
});
if (!pickerResult.cancelled) {
uploadResponse = await uploadImageAsync(pickerResult.uri);
uploadResult = await uploadResponse.json();
this.setState({
image: uploadResult.location
});
}
} catch (e) {
console.log({ uploadResponse });
console.log({ uploadResult });
console.log({ e });
alert('Upload failed, sorry :(');
} finally {
this.setState({
uploading: false
});
}
};
}
async function uploadImageAsync(uri) {
let apiUrl = 'http://elieatme.com/kamel/uploads.php';
let uriParts = uri.split('.');
let fileType = uriParts[uriParts.length - 1];
var datetime = moment()
.utcOffset('+02:00')
.format('YYYY-MM-DD hh:mm:ss a');
let formData = new FormData();
formData.append('fileToUpload', {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`,
});
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
return fetch(apiUrl, options);
}
export default App;
to function code below
function App() {
const [image, setImage] = useState(null);
const [uploading, setUploading] = useState(false);
let pickerResult;
return (
...
);
function _takePhoto() {
const {
status: cameraPerm
} = Permissions.askAsync(Permissions.CAMERA);
const {
status: cameraRollPerm
} = Permissions.askAsync(Permissions.CAMERA_ROLL);
// only if user allows permission to camera AND camera roll
if (cameraPerm === 'granted' && cameraRollPerm === 'granted') {
pickerResult = ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [4, 3],
quality: 0.2,
});
_handleImagePicked(pickerResult);
}
}
function _handleImagePicked() {
let uploadResponse, uploadResult;
try {
setUploading(true);
if (!pickerResult.cancelled) {
uploadResponse = uploadImageAsync(pickerResult.uri);
uploadResult = uploadResponse.json();
setImage(uploadResult.location);
}
} catch (e) {
console.log({ uploadResponse });
console.log({ uploadResult });
console.log({ e });
alert('Upload failed, sorry :(');
} finally {
setUploading(false);
}
}
}
function uploadImageAsync(uri) {
let apiUrl = 'http://elieatme.com/kamel/uploads.php';
let uriParts = uri.split('.');
let fileType = uriParts[uriParts.length - 1];
var datetime = moment()
.utcOffset('+02:00')
.format('YYYY-MM-DD hh:mm:ss a');
let formData = new FormData();
formData.append('fileToUpload', {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`,
});
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
return fetch(apiUrl, options);
}
export default App;

Please check where you have closed your function app.
You have closed your app function after _handleImagePicked().
And after return statement none of you code going to execute.
function App() {
const [image, setImage] = useState(null);
const [uploading, setUploading] = useState(false);
let pickerResult;
return (
...
);
} /// Close app function
function _takePhoto() {
const {
status: cameraPerm
} = Permissions.askAsync(Permissions.CAMERA);
const {
status: cameraRollPerm
} = Permissions.askAsync(Permissions.CAMERA_ROLL);
// only if user allows permission to camera AND camera roll
if (cameraPerm === 'granted' && cameraRollPerm === 'granted') {
pickerResult = ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [4, 3],
quality: 0.2,
});
_handleImagePicked(pickerResult);
}
}
function _handleImagePicked() {
let uploadResponse, uploadResult;
try {
setUploading(true);
if (!pickerResult.cancelled) {
uploadResponse = uploadImageAsync(pickerResult.uri);
uploadResult = uploadResponse.json();
setImage(uploadResult.location);
}
} catch (e) {
console.log({ uploadResponse });
console.log({ uploadResult });
console.log({ e });
alert('Upload failed, sorry :(');
} finally {
setUploading(false);
}
}
}/// Remove this closing
function uploadImageAsync(uri) {
let apiUrl = 'http://elieatme.com/kamel/uploads.php';
let uriParts = uri.split('.');
let fileType = uriParts[uriParts.length - 1];
var datetime = moment()
.utcOffset('+02:00')
.format('YYYY-MM-DD hh:mm:ss a');
let formData = new FormData();
formData.append('fileToUpload', {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`,
});
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
return fetch(apiUrl, options);
}
export default App;

Related

Old login token is not getting removed on re-login after successfull log-out

On Log-out i am clearing cookies like this:
const logoutUser = () => {
setUserData(undefined);
Cookies.remove('admin_details');
};
and also updating headers through auth link in Apollo Client like this:
const authLink = new ApolloLink((operation, forward) => {
// add the authorization to the headers
const token = getToken();
if (token) {
operation.setContext(({headers = {}}) => ({
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
}));
} else {
operation.setContext(({headers = {}}) => ({
headers: {
...headers,
},
}));
}
return forward(operation);
});
So I am not sure why the previous header token is set even after successfully log-out
Here is my APOLLO graphql setup file
const getToken = (): string | undefined => {
const adminDetails = Cookies.get('admin_details');
if (adminDetails) {
const userDataCookies = JSON.parse(
adminDetails,
) as AdminLoginMutation['login'];
return userDataCookies.access_token;
}
return undefined;
};
const logoutAndRedirectToLogin = () => {
Cookies.remove('admin_details');
window.location.reload();
window.location.replace('/auth/login');
};
const getRequestHeaders = () => {
let header;
const token = getToken();
if (token) {
header = {
authorization: token ? `Bearer ${token}` : undefined,
};
} else {
header = {
isadmin: true,
};
}
return header;
};
const getUrl = (): {
ws: string;
http: string;
} => {
if (
process.env.END_POINT &&
typeof process.env.END_POINT === 'string'
) {
if (process.env.END_POINT.includes('localhost')) {
return {
ws: 'ws://' + process.env.END_POINT,
http: 'http://' + process.env.END_POINT,
};
} else {
return {
ws: 'wss://' + process.env.END_POINT,
http: 'https://' + process.env.END_POINT,
};
}
} else {
return {ws: '', http: ''};
}
};
const httpLink = createHttpLink({
uri: getUrl().http,
headers: getRequestHeaders(),
});
const wsLink = new GraphQLWsLink(
createWsClient({
url: getUrl().ws,
connectionParams: {
headers: getRequestHeaders(),
},
}),
);
const authLink = new ApolloLink((operation, forward) => {
// add the authorization to the headers
const token = getToken();
if (token) {
operation.setContext(({headers = {}}) => ({
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
}));
} else {
operation.setContext(({headers = {}}) => ({
headers: {
...headers,
},
}));
}
return forward(operation);
});
const returnConnectionLink = (): ApolloLink => {
return split(
({query}) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
};
const splitLink = returnConnectionLink();
const errorLink = onError(({networkError, graphQLErrors}) => {
// To retry on network errors, we recommend the RetryLink
// instead of the onError link. This just logs the error.
if (networkError) {
if (
networkError.message.includes('authorization') ||
networkError.message.includes('unauthorized')
) {
logoutAndRedirectToLogin();
}
}
if (graphQLErrors) {
graphQLErrors.forEach(({extensions: {code}}) => {
if (code === 'UNAUTHENTICATED') {
logoutAndRedirectToLogin();
}
});
}
});
const cache = new InMemoryCache();
const links: Array<ApolloLink | RequestHandler> = [splitLink, errorLink];
export const graphqlClient = new ApolloClient({
cache: cache,
link: authLink.concat(ApolloLink.from(links)),
ssrMode: typeof window === 'undefined',
name: process.env.REACT_PUBLIC_APP_NAME
? process.env.REACT_PUBLIC_APP_NAME + '_web'
: 'web',
version: process.env.REACT_PUBLIC_APP_VERSION,
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
},
},
});
-Basically i want that,
Old login token should removed on re-login after successfull log-out
-NOTE
This issue comes sometimes but not everytime so not sure where am i going wrong
Any help would be appreciated. THANK YOU :)

Duplicate data saving on MongoDB

Hello I'm having a problem on my function save on my react project.
onSubmit={async (data, { setSubmitting, resetForm }) => {
for (var i = 0; i < selectedImageFiles.length; i++) {
const urlLink = await generateUploadUrl(selectedImageFiles[i].type);
const to_base64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
let blob = await to_base64(selectedImageFiles[i]);
let binary = atob(blob.split(",")[1]);
let array = [];
for (var x = 0; x < binary.length; x++) {
array.push(binary.charCodeAt(x));
}
let blobData = new Blob([new Uint8Array(array)], {
type: selectedImageFiles[i].type,
});
const uploadImageLink = await uploadImage(urlLink, blobData);
const newUploadImageLink = uploadImageLink.url.split("?")[0];
let productData = {
...data,
shopId: userShop._id,
images: selectedImageFiles,
category: collectCategoryId()[0],
};
addProduct(productData, userShop._id, newUploadImageLink).then(
(response) => {
if (response.status === 200) {
response.json().then((result) => {
setSubmitting(false); });
} else {
response.json().then((result) => {
setSubmitting(false);
});
}
}
);
}
}}
>
When I upload 2 files it also create 2 files on my database with same image link on both.
What I want is to create 1 data on database then the images.url must be different link from what I uploaded.
data number 1 that is inserted
{
"_id": {
"$oid": "62395b2faff15038acab7d0e"
},
"images": [{
"url": "https://devs.s3.ap-southeast-1.amazonaws.com/1647926063980.png",
}, {
"url": "https://devs.s3.ap-southeast-1.amazonaws.com/1647926063980.png",
}],
}
data number 2 that is inserted
{
"_id": {
"$oid": "62395b2faff15038acab7d0e"
},
"images": [{
"url": "https://devs.s3.ap-southeast-1.amazonaws.com/1647926063313.jpg",
}, {
"url": "https://devs.s3.ap-southeast-1.amazonaws.com/1647926063313.jpg",
}],
}
this is my addProduct
export const addProduct = async (productData, shopId, url) => {
const ls = new SecureLS({ encodingType: "aes" });
const token = ls.get("token");
const formdata = new FormData();
// console.log(productData.name);
for (let index = 0; index < productData.images.length; index++) {
formdata.append("file", productData.images[index]);
}
formdata.append("category", productData.category);
formdata.append("name", productData.name);
formdata.append("quantity", productData.quantity);
formdata.append("price", productData.price);
formdata.append("description", productData.description);
formdata.append("ingredients", productData.ingredients);
formdata.append("url", url);
return await fetch(`${API}/product/${shopId}`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: formdata,
})
.then((response) => {
return response;
})
.catch((err) => {
//console.log(err)
return err;
});
};
maybe something like this you need to be re debug and check addProduct last parameter :
onSubmit = async (data, { setSubmitting, resetForm }) => {
let filesUrls = [];
for (var i = 0; i < selectedImageFiles.length; i++) {
const urlLink = await generateUploadUrl(selectedImageFiles[i].type);
const to_base64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
let blob = await to_base64(selectedImageFiles[i]);
let binary = atob(blob.split(",")[1]);
let array = [];
for (var x = 0; x < binary.length; x++) {
array.push(binary.charCodeAt(x));
}
let blobData = new Blob([new Uint8Array(array)], {
type: selectedImageFiles[i].type,
});
const uploadImageLink = await uploadImage(urlLink, blobData);
const newUploadImageLink = uploadImageLink.url.split("?")[0];
filesUrls.push(newUploadImageLink);
}
let productData = {
...data,
shopId: userShop._id,
images: filesUrls,
category: collectCategoryId()[0],
};
addProduct(productData, userShop._id).then(
(response) => {
if (response.status === 200) {
response.json().then((result) => {
setSubmitting(false);
});
} else {
response.json().then((result) => {
setSubmitting(false);
});
}
});
}

react TypeError: Cannot read property 'fulfilled' of undefined on Redux tool kit

I just compiled my code and it prints "TypeError: Cannot read property 'fulfilled' of undefined"
it seems like I have to add initial value for fulfilled but I have no idea how to start.
should I convert my .js to ts and add interface for the code below?
Please help me to solve this issue.
this is my slice.js file for Redux Tool kit
import { createSlice, creatAsyncThunk , createAsyncThunk} from '#reduxjs/toolkit';
export const userSlice = createSlice({
name: 'user',
initialState: {
username: '',
email: '',
isFetching: false,
isSuccess: false,
isError: false,
errorMessage: '',
},
reducers: {
clearState: (state) => {
state.isError = false;
state.isSuccess = false;
state.isFetching = false;
return state;
},
},
exrtraReducers: {
[signupUser.fulfilled]: (state, { payload }) => {
state.isFetching = false;
state.isSuccess = true;
state.email = payload.user.email;
state.username = payload.user.name;
},
[signupUser.pending]: (state) => {
state.isFetching= true;
},
[signupUser.rejected]: (state, { payload }) => {
state.isFetching = false;
state.isError = true;
state.errorMessage = payload.method;
},
[loginUser.fulfilled]: (state, { payload }) => {
state.email = payload.email;
state.username = payload.name;
state.isFetching = false;
state.isSuccess = true;
return state;
},
[loginUser.rejected]: (state, { payload }) => {
console.log('payload', payload);
state.isFetching = false;
state.isError = true;
state.errorMessage = payload.message;
},
[loginUser.pending]: (state) => {
state.isFetching = true;
},
},
});
export const userSelector = (state) => state.user;
export const signupUser = createAsyncThunk(
'users/signupUser',
async ({ name, email, password }, thunkAPI ) => {
try {
const response = await fetch (
'https:/...',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
email,
password,
}),
}
);
let data = await response.json();
console.log('data : ', data);
if (response.status === 200) {
localStorage.setItem('token', data.token);
return { ...data, username: name, email: email };
} else {
return thunkAPI.rejectWithValue(data);
}
} catch (e) {
console.log('Error', e.response.data);
return thunkAPI.rejectWithValue(e.response.data);
}
}
);
export const loginUser = createAsyncThunk(
'users/login',
async ({ email, password }, thunkAPI ) => {
try {
const response = await fetch(
'https://...',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
}),
}
);
let data = await response.json();
console.log('response', data);
if (response.status === 200) {
localStorage.setItem('token', data.token);
return data;
} else {
return thunkAPI.rejectWithValue(data);
}
} catch (e) {
console.log('Error', e.response.data);
thunkAPI.rejectWithValue(e.response.data);
}
}
);
export const fetchUserBytoken = createAsyncThunk(
'users/fetchUserByToken',
async ({ token }, thunkAPI) => {
try {
const response = await fetch(
'https://...',
{
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: token,
'Content-Type': 'application/json',
},
}
);
let data = await response.json();
console.log('data', data, response.status);
if (response.status === 200) {
return { ...data };
} else {
return thunkAPI.rejectWithValue(data);
}
} catch (e) {
console.log('Error', e.response.data);
return thunkAPI.rejectWithValue(e.response.data);
}
}
);
Your functions are all correct. The only issue is the order. You cannot use the variables signupUser etc before they are defined. You need to rearrange your file so that the thunk actions creators come before the createSlice.
Like this:
import { createSlice, createAsyncThunk} from '#reduxjs/toolkit';
export const signupUser = createAsyncThunk( ...
export const loginUser = createAsyncThunk( ...
export const fetchUserBytoken = createAsyncThunk( ...
export const userSlice = createSlice({ ...
export const userSelector = ...

Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'uri.split')]on React Native Expo

I got a problem when upload image on react native
and here is my code
_pickImage = async () => {
await Permissions.askAsync(Permissions.CAMERA_ROLL);
const { cancelled, uri } = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 4],
base64: true
});
if (!cancelled) this.setState({ ImageKTP: uri });
this.createFormData();
};
and here is createFormData
createFormData = async (uri) => {
const {ImageKTP} = this.state;
let imageUri = uri.split('.');
let fileType = uriParts[uriParts.length - 1];
let formData = new FormData();
formData.append('ImageKTP', {
imageUri,
name: `ImageKTP.${fileType}`,
type: `image/${fileType}`,
});
fetch('http://192.168.0.20/profile.php?ImageKTP=' + ImageKTP,{
method: 'POST',
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
body: formData
})
.then((response) => response.json())
.then((responseJson) =>{
alert(responseJson);
})
.catch((error)=>{
console.error(error);
});
};
Any Solution for this? I still dont get it how to get the uri
Thank you
You need to call createFromData only when you successfully have uri set
if (!cancelled) {
this.setState({ ImageKTP: uri }, () => {
this.createFormData();
});
}
createFormData = async uri => {
const { ImageKTP } = this.state;
if (!ImageKTP) return;
/** Your processing code... */
};

How to create a Spotify playlist using react?

I am trying to create a playlist on localhost and then have the list I created to be saved to Spotify. Can someone help why Save to Spotify button might not be working? Everything else seems fine, I have doubts about the fetching part I used but can't figure out what the issue might be.
Screenshot of the page:
And there is the Spotify.js code:
import { SearchBar } from '../components/SearchBar/SearchBar';
const clientId = 'I've put my client id';
const redirectUri = 'http://localhost:3000/callback/';
let accessToken;
const Spotify = {
getAccessToken() {
if (accessToken) {
return accessToken;
}
//check for access token match
const accessTokenMatch = window.location.href.match(/access_token=([^&]*)/);
const expiresInMatch = window.location.href.match(/expires_in=([^&]*)/);
if (accessTokenMatch && expiresInMatch) {
accessToken = accessTokenMatch[1];
let expiresIn = Number(expiresInMatch[1]);
//This clears the parameters, allowing to grab new access token then it expires
window.setTimeout(() => (accessToken = ''), expiresIn * 1000);
window.history.pushState('Access Token', null, '/');
return accessToken;
} else {
const accessUrl = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectUri}`;
window.location = accessUrl;
}
},
search(term) {
const accessToken = Spotify.getAccessToken();
return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
headers: { Authorization: `Bearer ${accessToken}` },
})
.then((response) => {
return response.json();
})
.then((jsonResponse) => {
if (!jsonResponse.tracks) {
return [];
}
return jsonResponse.tracks.items.map((track) => ({
id: track.id,
name: track.name,
artists: track.artists[0].name,
album: track.album.name,
uri: track.uri,
}));
});
},
savePlaylist(name, trackUris) {
if (!name || !trackUris.length) {
return;
}
const accessToken = Spotify.getAccessToken();
const headers = { Authorization: `Bearer ${accessToken}` };
let userId;
return fetch(`https://api.spotify.com/v1/me`, { headers: headers })
.then((response) => response.json())
.then((jsonResponse) => (userId = jsonResponse.id))
.then((userId) => {
return fetch(`/v1/users/${userId}/playlists`, {
headers: headers,
method: 'POST',
body: JSON.stringify({ name: name }),
})
.then((response) => response.json())
.then((jsonResponse) => {
const playlistId = jsonResponse.id;
return fetch(`/v1/users/${userId}/playlists/${playlistId}/tracks`, {
headers: headers,
method: 'POST',
body: JSON.stringify({ uris: trackUris }),
});
});
});
},
};
export default Spotify;
Here is the screenshot of Element > Console:
I had an fetch error, updated as below and working now.
let accessToken;
const Spotify = {
getAccessToken() {
if (accessToken) {
return accessToken;
}
//check for access token match
const accessTokenMatch = window.location.href.match(/access_token=([^&]*)/);
const expiresInMatch = window.location.href.match(/expires_in=([^&]*)/);
if (accessTokenMatch && expiresInMatch) {
accessToken = accessTokenMatch[1];
let expiresIn = Number(expiresInMatch[1]);
//This clears the parameters, allowing to grab new access token then it expires
window.setTimeout(() => (accessToken = ''), expiresIn * 1000);
window.history.pushState('Access Token', null, '/');
return accessToken;
} else {
const accessUrl = `https://accounts.spotify.com/authorize?client_id=${clientId}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectUri}`;
window.location = accessUrl;
}
},
search(term) {
const accessToken = Spotify.getAccessToken();
return fetch(`https://api.spotify.com/v1/search?type=track&q=${term}`, {
headers: { Authorization: `Bearer ${accessToken}` },
})
.then((response) => {
return response.json();
})
.then((jsonResponse) => {
if (!jsonResponse.tracks) {
return [];
}
return jsonResponse.tracks.items.map((track) => ({
id: track.id,
name: track.name,
artists: track.artists[0].name,
album: track.album.name,
uri: track.uri,
}));
});
},
savePlaylist(name, trackUris) {
if (!name || !trackUris.length) {
return;
}
const accessToken = Spotify.getAccessToken();
const headers = { Authorization: `Bearer ${accessToken}` };
let userID;
return fetch('https://api.spotify.com/v1/me', { headers: headers })
.then((response) => response.json())
.then((jsonResponse) => {
userID = jsonResponse.id;
return fetch(`https://api.spotify.com/v1/users/${userID}/playlists`, {
method: 'POST',
headers: headers,
body: JSON.stringify({ name: name }),
})
.then((response) => response.json())
.then((jsonResponse) => {
const playlistID = jsonResponse.id;
return fetch(
`https://api.spotify.com/v1/users/${userID}/playlists/${playlistID}/tracks`,
{
method: 'POST',
headers: headers,
body: JSON.stringify({ uris: trackUris }),
}
);
});
});
}, // end of savePlaylist method
}; // end of Spotify object
export default Spotify;

Resources