How do i upload a image file with Axios from a form - reactjs

I need to upload a image file to my API with Axios calls
But i keep getting a error code 500 no matter what i do?
Here is what i have done so far.
import React, { useState, useContext, useEffect } from "react";
import Axios from "axios";
// Context
import { TokenDataContext } from "../Contexts/TokenContext";
// Components
import AdminNav from "../components/admin/AdminNav";
const AddAssets = () => {
const { token } = useContext(TokenDataContext);
const header = {
headers: {
Authorization: `Bearer ${token}`,
},
};
// Create volunteer
const [assetCreated, setAssetCreated] = useState(false);
const [badAsset, setBadAsset] = useState(false);
function handleVolunteerCreateInfo(e) {
e.preventDefault();
setAssetCreated(false);
setBadAsset(false);
const form = e.target;
const file = form[0].files;
// console.log(username + ' ' + password);
Axios.post(
"http://localhost:4000/api/v1/assets",
{
file: file,
},
header
)
.then((response) => {
if (response.status === 200) {
setAssetCreated(true);
setBadAsset(false);
}
})
.catch((error) => {
setAssetCreated(false);
setBadAsset(true);
});
}
Here's what it looks like in insomnia
and here is the error

Related

React Why Form data clear after switch loading status

I created a form for registration, and added a loader spinner. But the loader jumps quickly, it is almost imperceptible. Is it correct to add a small delay using setTimeout in this case? When call setLoader(false), the is shown again and all inputs becomes empty. The data filled by the user must not disappear. How to do this, and also so that setLoader(false) is set only after receiving a response from the api? Thanks.
import React, { useState } from "react";
import { Form } from "react-bootstrap";
import Loader from "./Loader";
import {toast} from "react-toastify";
const AdministratorSignIn = () => {
const [loader, setLoader] = useState(false)
const newAdministrator = async (e) => {
e.preventDefault()
setLoader(true)
let response = await fetch('/api/v1.0/sign-up/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
'email': e.target.email.value,
'first_name': e.target.first_name.value,
'last_name': e.target.last_name.value
}
)
})
if (response.status === 201) {
toast("Success", {type: "success"})
setTimeout(() => {setLoader(false)}, 200)
}
else if (response.status === 400) {
toast("Warning"), {type: "warning"})
setTimeout(() => {setLoader(false)}, 200)
}
}
return (
{ !loader ? (
<Form onSubmit={newAdministrator}>
... some inputs here ...
</Form>
)
: (
<Loader />
)
}
)
}
export default AdministratorSignIn

Next.js - React Custom Hook throws Invalid hook call

Hi I am quite new to react and this is for a learning project.
In react under next.js want to check for the existence of a certain folder on the server. To achieve that I implemented an api twigExists.js in pages/api and a custom hook twigExistsRequest.js in the library folder:
import {useEffect, useRef} from "react";
import {webApiUrl} from "#/library/webHelpers";
export function useTwigExistsRequest({
parentDirSegment,
name,
action,
treeStateDispatch
}) {
const nameExists = useRef('not');
useEffect(() => {
if ('' !== name) {
async function fetchNameValidation() {
try {
const response = await fetch(
webApiUrl() + '/branchName',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({parentDirSegment, name})
}
);
const answer = await response.json();
if (undefined !== answer['exists']) {
nameExists.current = answer['exists'];
}
else if (undefined !== answer['err']) {
console.log(answer['err']);
}
} catch (err) {
console.log(err);
}
}
fetchNameValidation().then(() => {
nameExists.current === 'exists'
&& treeStateDispatch({
action,
name,
dirSegment: parentDirSegment
});
})
}
});
}
The following error is thrown at the useRef line, line 10:
Error: Invalid hook call. Hooks can only be called inside of the body
of a function component.
I am using an almost identical approach to get the structure of a special folder with its subfolders and it is working fine. Working example:
import {useEffect, useRef} from "react";
import {webApiUrl} from "#/library/webHelpers";
export default function useChangeBranchRequest({
data,
setData
}) {
let postData;
const storeEffect = useRef(0);
if ('skip' !== data) {
storeEffect.current += 1;
postData = JSON.stringify(data);
}
useEffect(() => {
if (0 !== storeEffect.current) {
async function fetchData() {
try {
const response = await fetch(
webApiUrl() + '/changeBranch',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: postData
});
const json = await response.json();
setData(JSON.parse(json['tree']));
} catch (error) {
console.log(error);
}
}
fetchData()
.then(() => {
return (<></>);
});
}
}, [storeEffect.current]);
}
I can't see: What is wrong in the first example??
Edit due to question: useTwigExistsRequest is called from this file:
import {useTwigExistsRequest} from "#/library/twigExistsRequest";
export default function twigExistsHandler({
parentDirSegment,
name,
action,
treeStateDispatch
}) {
useTwigExistsRequest({
parentDirSegment,
action,
name,
treeStateDispatch
});
}
trying to avoid a direct call from:
import {ACTIONS} from "#/library/common";
import {useState} from "react";
import twigExistsHandler from "#/library/twigExistsHandler";
export default function PlgButton({dirSegment, action, text, treeStateDispatch}) {
const [info, SetInfo] = useState('');
const [parentDirSegment, SetParentDirSegment] = useState('');
// name validation, triggered by SetInfo. Returns strings 'false' or 'true':
// reset Button after execution
if (info) SetInfo('');
return (
<button
className="btn btn-secondary btn-sm new-plg-btn"
onClick={() => {
clickHandler(action);
}}
>
{text}
</button>
);
function clickHandler(action) {
let name;
switch (action) {
case ACTIONS.add:
name = window.prompt('New name:');
twigExistsHandler({
parentDirSegment: dirSegment,
name,
action,
treeStateDispatch
});
break;
case ACTIONS.dup:
name = window.prompt('Dup name:');
twigExistsHandler({
parentDirSegment: dirSegment.slice(0,dirSegment.lastIndexOf('/')),
name,
action,
treeStateDispatch
});
break;
case ACTIONS.del:
window.confirm('Irrevocably delete the whole playground?')
&& treeStateDispatch({
info: '',
dirSegment,
action
});
break;
}
}
}

Fetch the image and display it with Authorization in react

I'm going to fetch an image from ASP.NET core 5 web API and display it in react (with Authorization)
But I get the following error
Error image
when I remove Authorize and open the photo in the browser, the photo is displayed correctly
This is my code in react :
import axios from "axios";
import React, { useEffect, useState } from "react";
import { Buffer } from "buffer";
const Test = () => {
const [source, setSource] = useState();
useEffect(async () => {
const API_URL =
process.env.REACT_APP_URL +
"/Images/testimg/94e51231-cab8-4c51-8ee5-15b0da3164a4.jpg";
const token = JSON.parse(localStorage.getItem("user")).token;
try {
const response = await axios.get(API_URL, {
headers: {
responseType: "arraybuffer",
Authorization: `Bearer ${token}`,
},
});
if (response) {
console.log(response);
var buffer = Buffer.from(response.data,"base64")
setSource(buffer);
}
} catch (error) {
console.log(error);
}
}, []);
console.log(source);
return (
<img
id="test-img"
src={`data:image/jpeg;charset=utf-8;base64,${source}`}
/>
);
};
export default Test;
And This is my code in ASP.NET core 5 web API:
[Route("testimg/{name}")]
[HttpGet]
[Authorize]
public IActionResult testimg(string name)
{
string curentPath = Directory.GetCurrentDirectory();
string fullPath = Path.Combine(curentPath, $"resources\\{name}");
var image = System.IO.File.OpenRead(fullPath);
return File(image, "image/jpeg");
}

React / useEffect doesn't call/dispatch action creator

This should work ->
import { useEffect } from 'react'
import { useSelector, useDispatch } from "react-redux";
import CheckLoginStatus from "../../utils/CheckLoginStatus";
import ProductDetailDisplay from '../../components/product/ProductDetailDisplay'
// using #reduxjs/toolkit as Redux state / store thing
import { selectProduct, getProductById } from '../products/productsSlice'
function handleAddToCart(){
alert('handleAddToCart')
}
export default function ProductDetail ( props ) {
let { productId } = props
CheckLoginStatus()
const dispatch = useDispatch()
const productData = useSelector(selectProduct)
useEffect(() => {
console.log('useEffect()') // <<< 'useEffect()' appears in console
dispatch(getProductById(productId)); // <<< it looks like it's never called
},[])
return <ProductDetailDisplay data={productData} handleAddToCart={ handleAddToCart }/>
}
However, the 'dispatch(getProductById(productId))' inside of useEffect doesn't happen. (edit) However, the console.log('useEffect()') line does execute, and the message appears in the console.
I've been staring at this for an entire day, trying out all of the combinations of solutions I can think of, and have nothing.
Can someone please let me know where I'm missing the point with this code? It should work, and a single product record should be available to ProductDetailDisplay. But it looks like 'getProductById(productId))' never gets called.
Thanks in advance.
(edit) krirkrirk, here is the code for getProductById ->
export const getProductById = createAsyncThunk (
'products/getProductById',
async (product_id) => {
let theApiUrl = API_BASE_URL + `/api/v1/product/${product_id}`
let authToken = useSelector(selectJwtToken)
console.log('getProductById', product_id)
try {
const response = await fetch(
theApiUrl,
{
method: 'GET',
headers: {
'Accept': "*/*",
'Content-Type': "application/json",
'Authorization': `Bearer ${authToken}`,
},
credentials: 'include',
}
)
let data = await response.json();
if (response.status === 200) {
// console.log('getProductById 200', data[0])
console.log('productById ', data)
return data[0] // FIXME: shouldn't have to juggle arrays when assigning to state...
} else if (response.status === 401) {
console.log('getProductById get request auth fail.')
// return thunkAPI.rejectWithValue(data)
}
} catch (e) {
console.log("Error: ", e.response.data)
// return thunkAPI.rejectWithValue(e.response.data)
}
}
) // end getProductById

How to create a custom Hooks in reactjs hooks?

I was trying to create a custom Hooks for handling input HTTP request from any component by simply calling the useCustomHooks but its getting failed and error is
Can not use keyword 'await' outside an async function
All i made is a handler that triggers http request custom component method
import { useState } from 'react';
import axios from "axios";
const useHttpReqHandler = () => {
const [result, setResult] = useState();
const apiMethod = async ({url , data , method}) => {
let options = {
method,
url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
data
};
let response = await axios(options);
const UpdatedData = await response.data;
console.log(UpdatedData)
setResult(UpdatedData);
}
return [result, apiMethod];
};
export default useHttpReqHandler;
Now i can use this hook in my code and on any event handler just call callAPI returned from the hook like this
const MyFunc = () => {
const [apiResult, apiMethod] = useHttpReqHandler();
const captchValidation = () => {
const x = result.toString();;
const y = inputValue.toString();;
if ( x === y) {
apiMethod({url: 'some url here', data: {"email": email}, method: 'post'});
alert("success")
}
else {
alert("fail")
}
}
Is is a correct approch ? as i am beginner in Reactjs
Here is a working version:
useHttpReqHandler.jsx
import { useState } from 'react';
import axios from "axios";
const useHttpReqHandler = () => {
const [apiResult, setApiResult] = useState();
const apiMethod = async ({url , data , method}) => {
let options = {
method,
url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
data
};
let response = await axios(options);
let responseOK = response && response.status === 200 && response.statusText === 'OK';
if (responseOK) {
const data = await response.data;
console.log(data)
setApiResult(data);
}
}
return [apiResult, apiMethod];
};
export default useHttpReqHandler;
What's important here:
await is called inside an async function (apiMethod)
The result is stored in a local state (apiResult)
The function returns an array [apiResult, apiMethod]
How to use it:
const [apiResult, apiMethod] = useHttpReqHandler();
apiMethod({url: 'some url here', data: {"email": email}, method: 'post'});
Render the result:
return {apiResult};
In my opinion, it is better to use .then with Axios. and try to create for each method different functions "Get/Post...", why because in the GET method you need to useEffect, but it can not be the same case in POST method. in GET method useHttpReqHandler.js
import { useEffect, useState } from "react";
import axios from "axios";
// GET DATA
const useHttpReqHandler = (url) => {
const [httpData, setHttpData] = useState();
useEffect(() => {
axios
.get(url)
.then((axiosData) => {
// Axios DATA object
setHttpData(axiosData.data);
// you can check what is in the object by console.log(axiosData);
// also you can change the state, call functions...
})
.catch((error) => {
console.log(error);
});
}, []);
return httpData;
};
export default useHttpReqHandler;
in your main file
import useHttpReqHandler from "...."
const MyFunc = () => {
const getData = useHttpReqHandler("URL");
return (
<div>
...
</div>
)
}
I hope it helps
the same thing will be with POSt, PUT, DELETE ... you will create functions for each method that will handle the Http req

Resources