error boundary when using hooks to display data - javascript

I try to get user data when load page using hooks(in case useEffect), but i got error said "Consider adding an error boundary to your tree" and my app getting blank.
my code looks similar like below
still configure out how to fix it, but i dont know how. coz i new using react
const [ProfileData, setProfileData] = useState({});
const [ownerId, setOwnerId] = useState('')
let ProfileID = 12
const getId = async () => {
const responseData = await getUserData();
setOwnerId(responseData.ID);
};
this is my function to get data from API
const getProfileData = () => {
setLoading(true);
getId();
const jsonData = {
ID: ProfileID,
OwnerId: ownerId
};
const headers = {
'Access-Control-Allow-Headers': '*'
};
try {
axios
.post(
config.API_SERVER + 'SearchProfile',
{
Data: jsonData ,
},
headers
)
.then(function (response) {
if (response.data.status == 'Success') {
setProfileData(response.data.Data);
setLoading(false);
} else {
setProfileData({});
alert(response.data.status);
}
})
} catch (error) {
console.log(error);
}
};
this is my hooks
useEffect(() => {
const load = async () => {
try {
await getProfileData();
} catch (err) {
throw err
}
}
load()
}, []);
and this is my return to display data
return (
<p>{ProfileData.Name}</p>
)

Since you throw an error (throw err) but you don't catch it, you can omit that part, pass the error message to state, or use react-error-boundary.
useEffect(() => {
getProfileData();
}, []);

Related

ReactJS: How to properly reset or handle data from state

I have this working, when the user goes to this page, this line of code executes:
interface Badge {
id: string;
badge_name: string;
badge_description: string;
img64: string;
}
const [data, setData] = useState([] as any[]);
const [isPending, setisPending] = useState(true);
const [searchTerm, setSearchTerm] = useState("");
const onSearchChange = (e: any) => {
setSearchTerm(e.target.value);
};
const setDataWithImg = useCallback(async (badges: Badge[]) => {
let badgeWithImg: Badge[] = [];
const base64Flag = "data:image/png;base64,";
await Promise.all(
badges.map(async (badge: any) => {
const imgBuffer = badge.img_icon.data;
const imgBase64 = bufferToBase64(imgBuffer);
badge.imgBase64 = `${base64Flag}${imgBase64}`;
badgeWithImg.push(badge);
})
);
setData(badgeWithImg);
}, []);
const loadData = useCallback(async () => {
console.log("loadData");
try {
setisPending(true);
await BadgeService.loadData().then(
(res) => {
setDataWithImg(res.data);
setisPending(false);
},
(error) => {
setisPending(false);
}
);
} catch (err) {
console.log(err);
setisPending(false);
}
}, [setDataWithImg]);
useEffect(() => {
loadData();
}, [loadData]);
It will load the data from BadgeService.loadData and I have this function also that will search data from api, and this code will execute.
const onClickFilter = async (e: any) => {
e.preventDefault();
if (searchTerm === "") {
loadData();
} else {
try {
console.log("filterData");
setisPending(true);
await BadgeService.filterData({
badge_name: searchTerm,
}).then(
(res) => {
setDataWithImg(res.data);
setisPending(false);
},
(error) => {
setisPending(false);
}
);
} catch (err) {
console.log(err);
setisPending(false);
}
}
};
User has a search function and that code will execute, search function works fine, I want when user click filter with empty value in search, it will load the original loadData. I already tried console.log('Loaddata') to trace if my condition is working fine and it is ok, but when I check the network, it still executing the api call from filterData, not loadData
First load of the page:
When user fires search function:
Where user fires search function but empty search term:
Base on network logs:
The last request should be the badges only, not the with parameters..How I fix this? What Am I missing here?
Thank you!
Looking at your code, your if check in onClickFilter function seems wrong.
you can do something like
if(!searchTerm){
loadData();
}
Doing !searchTerm will return true for every "falsy" value (empty string, 0, null, false, undefined, NaN) whereas x == "" will only return true if x is null (or apparently undefined).
Please let me know if it works.
I got may issue fix by doing this,
I have this code in my service:
const loadData = () => {
config["params"] = {};
return axios.get(API_URL + "api/v1/badges", config).then((response) => {
//console.log("from loaddata..");
//console.log("load data", response);
return response;
});
};
const filterData = (data: any) => {
config["params"] = {
s: data,
};
return axios.get(API_URL + "api/v1/badges", config).then((response) => {
console.log("from filterdata..");
console.log("filter data", response);
return response;
})
;
I just added config["params"] = {}; this line of code to loadData
Thank you all!

how to set state using axios response data

I am having issues with setting state. When I try to set the state of setDataTemp() from axios the data sent into setDataTemp is blank. however if I just console log the data directly I get response. Not sure what wrong
setDataTemp is not empty
const [dataTemp, setDataTemp] = useState([]);
const _overlayFilder = async () => {
let source = axios.CancelToken.source();
await axios
.get(network + '/getOverlayList', {
cancelToken: source.token,
})
.then(response => {
removeRootUUID(response.data.items, response.data.items);
// console.log(response.data);
return response.data;
})
.then(response => {
setDataTemp(response.items);
})
.catch(function (e) {
if (axios.isCancel(e)) {
console.log(`request cancelled:${e.message}`);
} else {
console.log('another error happened:' + e.message);
}
})
.finally(() => {
console.log(dataTemp)
});
If I don't set the state setDataTemp and I just console.log instead I prints the data
const [dataTemp, setDataTemp] = useState([]);
const _overlayFilder = async () => {
let source = axios.CancelToken.source();
await axios
.get(network + '/getOverlayList', {
cancelToken: source.token,
})
.then(response => {
removeRootUUID(response.data.items, response.data.items);
// console.log(response.data);
return response.data;
})
.then(response => {
// the data that I want to set into setDataTemp
console.log(response.items);
})
.catch(function (e) {
if (axios.isCancel(e)) {
console.log(`request cancelled:${e.message}`);
} else {
console.log('another error happened:' + e.message);
}
})
You are mixing an async function handling using a Promise-like approach with your axios call.
Try to change your code like this:
const [dataTemp, setDataTemp] = useState([]);
const _overlayFilder = async () => {
try {
let source = axios.CancelToken.source();
const { data } = await axios.get(network + '/getOverlayList', {
cancelToken: source.token,
});
removeRootUUID(data.items, data.items);
setDataTemp(data.items);
console.log(dataTemp);
} catch (err) {
if (axios.isCancel(err)) {
console.log(`request cancelled:${e.message}`);
} else {
console.log('another error happened:' + e.message);
}
}
};

parsing data from an api call into a text file using axios

I am parsing data from an API call into a text file. However, I wanted to use async-await and break the call below call into 3 separate functions.
#!/usr/bin/env node
const yargs = require("yargs");
const axios = require("axios");
const fs = require("fs");
const options = yargs
.usage("Usage: -n <name>")
.option("n", {
alias: "name",
describe: "Your name",
type: "string",
demandOption: true,
})
.option("s", { alias: "search", describe: "Search Term", type: "string" })
.argv;
const greetings = `Hello ${options.name}!`;
console.log(greetings);
console.log("Here's a random joke for you: ");
const url = options.search
? `https://icanhazdadjoke.com/search?term${escape(options.search)}`
: " https://icanhazdadjoke.com/";
axios.get(url, { headers: { Accept: "application/json" } }).then((res) => {
if (options.search) {
res.data.results.forEach((j) => {
fs.appendFile("jokes.txt", "\n" + j.jokes, (err) => {});
});
if (res.data.results.length === 0) {
console.log("no joke found 😭");
}
} else {
fs.appendFile("jokes.txt", res.data.joke, (err) => {
if (err) throw err;
console.log("File Updated");
});
}
});
So the above code works absolutely fine and generates the file perfectly, however when I tried to break it into the following below functions, I just get undefined in the text file, I am not sure why this is happening.
const getJoke = async (url) => {
try {
const joke = await axios.get(url, {
headers: { Accept: "application/json" },
});
return joke;
} catch (error) {
console.error(error);
}
};
const parseJokes = (res) => {
if (options.search) {
res.data.results.forEach((j) => {
return `\n ${j.joke}`;
});
if (res.data.results.length === 0) {
console.log("no joke found 😭");
}
} else {
return res.data.joke;
}
};
const addJokeToFile = async () => {
const result = await getJoke(url)
.then((res) => {
parseJokes(res);
})
.catch((err) => {
console.error(`ERROR: ${err}`);
});
fs.appendFile("jokes.txt", result, (err) => {
console.error(err);
});
};
In the second (functional approach) addJokeToFile method, you are waiting for the promise to be resolved using both ways, await and .then, following modification to the code, might help you get through:
const addJokeToFile = async () => {
getJoke(url)
.then((res) => {
// Aside, we should also return some value from parseJokes function for "no joke found 😭" case, or return null and put a check here and only append to file when jokeString is not null.
const jokeString = parseJokes(res);
fs.appendFile("jokes.txt", jokeString, (err) => {
console.error(err);
});
})
.catch((err) => {
console.error(`ERROR: ${err}`);
});
};
Try using appendFile from 'fs/promises' so that you can stick with the async/await style. Since getJoke returns a promise I would expect result to be a Promise<string | undefined> depending on if any errors show up earlier in the chain.
const { appendFile } = require('fs/promises');
const addJokeToFile = async () => {
try {
const result = await getJoke(url);
const parsed = parseJokes(result);
await appendFile('jokes.txt', parsed);
} catch (err) {
console.error(err);
}
};

How do I cancel this axios request

I'm getting a memory leak when my browser is redirected away from this component. So I need to cancel it, but for some reason my cancel token isn't having any effect, and I'm wondering why.
Please take a look, below is my code:
const getBoards = async (**cancelToken**) => {
try {
if (localStorage.getItem("token") == null) {
throw new Error();
}
const response = await Axios.get("/boards", config, **{ cancelToken }**);
setBoards(response.data);
} catch (e) {}
};
useEffect(() => {
**const request = Axios.CancelToken.source();**
getBoards(request);
return () => {
**request.cancel();**
};
}, []);
You use the token via the .token property, you don't pass the entire object from source() as the token. From the documentation:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
So translating that to your code,
getBoards(request);
would be
getBoards(request.token);
// −−−−−−−−−−−−−−^^^^^^

Preventing Unnecessary Requests when update the input

How to preventing unnecessary requests when update the input?
I tried below solution.But in the App file, that search is declared but never used. I tried something like: https://alligator.io/react/live-search-with-axios/.
What is the variable let token in the fileutils.js. Should I assign let token = localStorage.getItem ('token') to this variable;?
App
import search from /.utils
class App extends Component {
constructor (props) {
super(props);
this.state = {
todos: [],
}
}
search = (query) => {
axios({
url: `/api/v1/todos/{query}`,
method: "GET"
})
.then(res => {
this.setState({
todos: res.data
});
})
.catch(error => {
console.log(error);
})
render () {
return (
<input onChange={this.search} />
)
}
}
utils.js
import axios from 'axios';
const makeRequestCreator = () => {
let token;
return (query) => {
// Check if we made a request
if(token){
// Cancel the previous request before making a new request
token.cancel()
}
// Create a new CancelToken
token = axios.CancelToken.source()
try{
const res = axios(query, {cancelToken: cancel.token})
const result = data.data
return result;
} catch(error) {
if(axios.isCancel(error)) {
// Handle if request was cancelled
console.log('Request canceled', error.message);
} else {
// Handle usual errors
console.log('Something went wrong: ', error.message)
}
}
}
}
const search = makeRequestCreator()
export default search;
You can do that with a function that delays executing of your onChange.you can use debounce function from lodash.js
// _.debounce(yourSearch function, delay time);
search(e){
let str = e.target.value;
_.debounce(() => yourFunction, 500);
}

Categories

Resources