How to remove a part of html on live in React - javascript

I've got components in my react app,
First:
const App = () => {
const [tasks, setTasks] = useState([])
useEffect(() =>{
getTasks(data => setTasks(data))
}, [])
const onNewTask = task => {
setTasks(prev => ([
...prev,
task
]))
}
const onRemoveTask = () => {
setTasks(prev => ([
...prev,
]))
}
return (
<>
<NewTask add={onNewTask}/>
<Task tasks={tasks} remove={onRemoveTask}/>,
</>
)
}
This component renders two childrens:
In comp newTask there is a method where user can add a new task, the method:
const addNewTask = e => {
e.preventDefault();
fetch(`${API_URL}/tasks`, {
method: 'POST',
headers: {
Authorization: API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify(inputs)
})
.then(response => response.json())
.then(data => add(data.data))
.catch(e => console.warn(e))
}
It works fine, user adds a tasks, and it automatically appears in HTML thanks to onNewTask method in App component.
My problem is something similar, but in case of removing the task, I've got a method in Task component:
const handleDeleteTask = e => {
e.preventDefault();
const taskToRemove = e.target.id;
console.log(taskToRemove)
taskToRemove ?
fetch(`${API_URL}/tasks/${taskToRemove}`, {
method: 'DELETE',
headers: {
Authorization: API_KEY,
"Content-Type": "application/json",
},
})
.then(remove())
.catch(err => console.warn(err))
:
console.log('Error')
}
It removes a task, but user needs to refresh page to make the task disappear from HTML.
I know that my method isn't correct. Can someone please tell me how do it?
Thanks in advance.

you need to update the task array and set the same in setTasks.
const onRemoveTask = (id) => {
const newTaskList = tasks.filter(item.id != id)
setTasks(newTaskList)
}

Related

How can i run a function in every screen user is navigating to?

how can I run a function in the whole app? like if that function is triggered then even if a user is navigating to a different screen then also that function will do its work until that function work is done how can I do this in react native? I want to do this with my PostImageHandler once postimagehandler is triggered then that function will run and it won't stop until the image is uploaded also user can navigate through different screens during that process
const [loading1, setLoading1] = useState(false)
const [loading2, setLoading2] = useState(false)
const [photo, setPhoto] = useState(null)
const { postImage } = route.params;
const PostImageHandler = useCallback(async () => {
if (!postImage.cancelled) {
const response = await fetch(postImage);
const blob = await response.blob();
const filename = postImage.substring(postImage.lastIndexOf('/') + 1);
const ref = firebase.storage().ref().child(filename);
const snapshot = await ref.put(blob);
const url = await snapshot.ref.getDownloadURL();
setPhoto(url)
console.log(url)
}
}, [postImage])
useEffect(() => {
PostImageHandler();
}, [PostImageHandler])
const handleUpload = useCallback(() => {
if (postImage != null) {
AsyncStorage.getItem('user')
.then(data => {
setLoading2(true)
fetch('https://mybackend.com/addpost', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: JSON.parse(data).user.email,
post: postImage,
})
})
.then(res => res.json())
.then(data => {
if (data.message == 'Photo added successfully') {
alert('Photo added successfully')
setLoading2(false)
navigation.navigate('home')
} else {
alert('Something went wrong, please try again')
setLoading2(false)
}
})
})
} else {
alert('Please wait photo is processing')
}
}, [photo, navigation, setLoading2]);

Returns an empty array

I am trying to get the data from this endpoint but I am getting an empty array. Can you help me with this? thanks
I've been trying to do it, with the other methods I have I can get the corresponding data.
I tried several ways but still can't find a solution.
http://localhost:8081/getmnemonicsandtagsforabm this is the methood
const DataTable = () => {
const provider = useContext(AppContext);
let [editServiceStatus, setEditServiceStatus] = useState(false);
let [configServiceStatusButton, setConfigServiceStatusButton] =
useState(false);
let [serviceItem_selected, setServiceItem_selected] = useState([]);
let [fetchServiceDetail, setFetchServiceDetail] = useState([]);
let sessionID = localStorage.getItem("session_id");
const [array_services, setArray_services] = useState({ khad_services: [] });
const [array_services2, setArray_services2] = useState({ khad_services: [] });
const [active_dropdown, setActive_dropdown] = useState(false);
const [active_serviceConfig, setActive_serviceConfig] = useState(false);
useEffect(() => {
let session_id = {
session_id: sessionID,
};
fetch("http://localhost:8081/getservicelist", {
method: "POST",
body: JSON.stringify(session_id),
})
.then((res) => res.json())
.then((data) => {
//console.log(`****__ data: __****: `, data);
localStorage.setItem("array_services", JSON.stringify(data));
setArray_services(data);
})
.catch((err) => console.log(err));
}, []);
useEffect(() => {
let session_id = {
session_id: sessionID,
};
fetch("http://localhost:8081/getmnemonicsandtagsforabm", {
method: "POST",
body: JSON.stringify(session_id),
})
.then((res) => res.json())
.then((data) => {
console.log(`****__ data:__****: `, data);
localStorage.setItem("mnemonicsAndTags", JSON.stringify(data));
localStorage.setItem("mnemonics", JSON.stringify(data.mnemonics));
localStorage.setItem("tags", JSON.stringify(data.tags));
localStorage.setItem("tagsForMnemonics", JSON.stringify(data.tagsForMnemonics));
setArray_services(data);
})
.catch((err) => console.log(err));
}, []);
I await the return of the array accordingly

How to make API calls in Vanilla JS

Am building a weather app using vanilla JS and weatherbit rapid API, but whenever I run the program, it logs an error Can not read properties of undefined (reading 'temp')
const tempValue = document.getElementsByClassName('temp')
// console.log(cityName)
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': '************************************',
'X-RapidAPI-Host': 'weatherbit-v1-mashape.p.rapidapi.com'
}
}
document.getElementById('submit').addEventListener('click', e => {
e.preventDefault()
fetch(
'https://weatherbit-v1-mashape.p.rapidapi.com/forecast/3hourly?lat=35.5&lon=-78.5',
options
)
.then(response => response.json())
.then(data => {
let tempval = data['temp']
tempValue.innerHtml = tempval
})
.catch(err => console.error(err))
})
pls consult the docs.
https://rapidapi.com/weatherbit/api/weather
response object structure is:
{
country_code:"US",
lon:-78.5,
data: [...],
city_name:"Four Oaks",
lat:35.5,
timezone:"America/New_York",
state_code:"NC",
}
To access 'temp'. use `
fetch(
'https://weatherbit-v1-mashape.p.rapidapi.com/forecast/3hourly?lat=35.5&lon=-78.5',
options
).then(response => {
const someItemIndex = 0;
console.log(response.data);
const tempval = response.data[someItemIndex].temp
tempValue.innerHtml = tempval
})
.catch(err => console.error(err))
there is no temp in response. and there is no any field 'temp' in data. Temp is defined only on iterable items of data array.
After some advice I received from this platform, I have managed to modify the code and it's working perfectly. The problem was in the way I was accessing the fields from the JSON. I am new to APIs and this is an excellent start for me thank you.
Modified Code
const tempValue = document.querySelector('.temp')
const cityName = document.querySelector('.city_name')
const humid = document.querySelector('.humidity')
const weatherValue = document.querySelector('.weather')
// console.log(cityName)
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': '30583b6ad4msh649637ae1b0f6d3p1edde0jsn53b7839146a2',
'X-RapidAPI-Host': 'weatherbit-v1-mashape.p.rapidapi.com'
}
}
document.getElementById('submit').addEventListener('click', e => {
e.preventDefault()
fetch(
'https://weatherbit-v1-mashape.p.rapidapi.com/forecast/3hourly?lat=35.5&lon=-78.5',
options
)
//Modified code
.then(response => response.json())
.then(response => {
const someItemIndex = 0
console.log(response.data)
const tempval = response.data[someItemIndex].temp
const cityval = response.city_name
const weatherval = response.data[someItemIndex].weather.description
// console.log(tempval)
tempValue.innerHTML = `<h3>Temperature: </h3>${tempval}&#x2103`
weatherValue.innerHTML = `<h3>Weather Description: </h3>${weatherval}`
cityName.innerHTML = `<h3>City Name: </h3>${cityval}`
})
.catch(err => console.error(err))
})

How to send POST request from React to Flask without submit button

Hey sorry I'm completely new to React and Javascript and I'm really confused about this. I'm trying to create a section where I will have a dropdown list in React. I have already fetched the data from Flask and now when I click my chosen option, I want to send the POST request to Flask (without clicking any submit button).
I was reading different answers and trying to figure it out so I used "fetch" while getting the data and "axios" when trying to send the request.
App.js
import React, { useEffect, useState } from "react"
import { DropdownItem } from "../Components/DropdownItem"
import Select from "react-select"
import axios from "axios"
export const DropdownPage = () => {
const [years, setYears] = useState([])
const [selectedYear, setSelectedYear] = useState("")
useEffect(() => {
fetch("http://127.0.0.1:5000/api", {
method: "GET",
headers: {
"Content-type": "application/json",
},
})
.then((res) => res.json())
.then((data) => {
setYears(data)
})
}, [])
const handleDropdownSelectYear = (e) => {
setSelectedYear(e.target.value)
}
const handleDropdownSubmitYear = (e) => {
e.preventDefault()
console.log(e)
axios
.post("http://127.0.0.1:5000/api/yearselect", selectedYear)
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
}
return (
<div>
<form method="post" onSubmit={handleDropdownSubmitYear}>
<select onChange={handleDropdownSelectYear}>
<option value="">Select Year</option>
{years.map((year) => (
<DropdownItem key={year.id} year={year}></DropdownItem>
))}
</select>
</form>
</div>
)
}
api.py
class Year(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
def __str__(self):
return f'{self.id} {self.content}'
def year_serializer(year):
return {'id': year.id,
'content': year.content}
#app.route('/api', methods=['GET'])
def index():
return jsonify([*map(year_serializer, Year.query.all())])
#app.route('/api/yearselect', methods=['POST'])
def yearselect():
if request.method == 'POST':
request_data = request.get_json(force=True)
year = Year(content=request_data['content'])
db.session.add(year)
db.session.commit()
return {"201": request_data['content']}
If there's any other information/code you need, please let me know. Also, I'm planning to recreate this image below. So, when I make my selection on the first dropdown, it should send a request to flask and narrow down the options for the next dropdown and so on. Let me know if you need any clarification. Thanks!!
If you want to send the POST request when a selection is made, you don't need a <form> or a submit handler.
Instead, add an effect hook that listens for changes to selectedYear
// if selectedYear is going to be an object, don't initialise it as a string
const [selectedYear, setSelectedYear] = useState();
useEffect(() => {
if (selectedYear) {
fetch("http://127.0.0.1:5000/api/yearselect", {
method: "POST",
body: JSON.stringify(selectedYear),
headers: { "content-type": "application/json" },
})
.then((res) => {
if (!res.ok) return Promise.reject(res);
return res.json();
})
.then((data) => {
// do something with data ¯\_(ツ)_/¯
})
.catch(console.error);
}
}, [selectedYear]); // effect hook dependencies
Effect hooks also run when the value is initialised so checking the value of selectedYear before making the request is advisable.
The Axios equivalent would be
axios.post("http://127.0.0.1:5000/api/yearselect", selectedYear)
.then(({ data }) => {
// do something with data
})
.catch(err => {
console.error(err.toJSON());
});
try it please .. You can send data to backend onchange functıon directly called handleDropdownSelectYear function
const handleDropdownSelectYear = (e) => {
setSelectedYear(e.target.value)
console.log(e)
axios
.post("http://127.0.0.1:5000/api/yearselect", e.target.value)
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
}
or you can use useeffect .
const handleDropdownSelectYear = (e) => {
setSelectedYear(e.target.value)
}
useEffect(() => {
if (selectedYear) {
axios
.post("http://127.0.0.1:5000/api/yearselect", selectedYear)
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
}
}, [selectedYear]);

UseEffect hook not work well when re update data?

I have a list of orders, I'm using FlatList to render them,
I have 2 main concepts should I have "Load More, Pull to Refresh"
In my case user can edit the order then pull to refresh to get the newly updated data, and another case for load more "pagination".
SO
Load more functionality work properly well, and gets the new data from the server and pushed to the state with the old data,
BUT pull to refresh not works, it's not updated the data when setState, although the function that gets data triggered, and I can see the updated data in the console, It just renders the old data!
Here's a code snippet.
const OpenedAppointments = () => {
const [openedAppointment, setOpenedAppointment] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [lastPage, setLastPage] = useState(null);
const [loading, setLoading] = useState(false);
const [isFetch, setIsFetch] = useState(false);
const loadMoreOrders = () => {
if (currentPage <= lastPage - 1) {
setLoading(true);
setCurrentPage((prevPage) => prevPage + 1);
console.log('loadMore??');
}
};
const getOpenOrders = useCallback(() => {
let AuthStr =
'Bearer ';
const headers = {
'Content-Type': 'application/json',
Authorization: AuthStr,
};
Api.post(
`/open_orders?page=${currentPage}`,
{},
{
headers,
},
)
.then((res) => {
let last_Page = res.data.open_orders.last_page;
let allOpenedOrders = res.data.open_orders.data;
console.log('allOpenedOrders', allOpenedOrders);
console.log('last_Page', last_Page);
console.log('currentPage', currentPage);
setLastPage(last_Page);
setOpenedAppointment((prevOpenedOrders) => [
...prevOpenedOrders,
...allOpenedOrders,
]);
setLoading(false);
setIsFetch(false);
})
.catch((err) => console.log('err', err));
}, [currentPage]);
// Delete Appointments
const cancelAppointem = (appointmentID) => {
let AuthStr =
'Bearer...';
const headers = {
'Content-Type': 'application/json',
Authorization: AuthStr,
};
Api.post(
'/cancel/order',
{
id: appointmentID,
},
{
headers,
},
)
.then((res) => {
setIsOpenedCancelModal((opened) => !opened);
console.log(res.data);
setOpenedAppointment((prev) =>
prev.filter((item) => item.id !== appointmentID),
); // works very well
})
.catch((err) => console.log(err));
};
const _refresh = () => {
setIsFetch(true);
getOpenOrders();
};
useEffect(() => {
getOpenOrders();
}, [getOpenOrders]);
const keyExtractor = (item, index) => String(index);
return (
<FlatList
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.flatListCon}
data={openedAppointment}
ListEmptyComponent={renderEmpty}
renderItem={renderItems}
keyExtractor={keyExtractor}
ListFooterComponent={_renderFooter}
onEndReached={loadMoreOrders}
onEndReachedThreshold={0.1}
onRefresh={_refresh}
refreshing={isFetch}
/>
);
};
Figure out the problem
At first render I got 5 orders from API, If I update the first order then pull to refresh, I got the same 5 order again but order number one is updated
So in getOpenOrders function, it merges old orders with new orders so I can see duplicated orders first 5 order "old data"
second 5 order "updated data".
But I have other concepts for load more "pagination" so it's should I have the merged arrays to get new order at the next page "2" with the prev order in the previous page "1"!
So how can I fix this?
Edit Data structure response
open_orders = [
{id: 14, status: "Cash", cost: "25.00", service_id: 11, vendor_id: 3, …}
{id: 15, status: "Cash", cost: "25.00", service_id: 11, vendor_id: 3, …}
...
]
Your effect should listen isFetch
const _refresh = () => {
setIsFetch(true);
};
useEffect(() => {
getOpenOrders();
}, [isFetch]);
const [updatePage, setUpdatePage] = useState(1)
const [isUpdate, setIsUpdate] = useState(false)
// call `setUpdatePage` when you edit the data
/**
* const edit = (record)=>{
* ...
* const updatePageIndex = openedAppointment.findIndex((item)=> item.id === record.id)
* const updatePageNum = Math.ceil(updatePageIndex/openedAppointment.length)
* setUpdatePage(updatePageNum)
* setIsUpdate(true)
* }
*
**/
const getOpenOrders = useCallback(() => {
const pageNum = isUpdate ? updatePage : currentPage
let AuthStr =
'Bearer ';
const headers = {
'Content-Type': 'application/json',
Authorization: AuthStr,
};
Api.post(
`/open_orders?page=${pageNum}`,
{},
{
headers,
},
)
.then((res) => {
let last_Page = res.data.open_orders.last_page;
let allOpenedOrders = res.data.open_orders.data;
...
if(openedAppointment.length > 0) {
const newOpenedOrders = openedAppointment.map((item)=>{
const target = allOpenedOrders.find(ele=> ele.id === item.id) || []
return {
...item,
...target,
}
})
setOpenedAppointment(newOpenedOrders);
} else {
setOpenedAppointment(allOpenedOrders)
}
setIsUpdate(false)
...
})
.catch((err) => console.log('err', err));
}, [currentPage]);

Categories