React State is not showing when used outside console log - javascript

I'm using antd with react to upload an image to each of my facilities.
The uploading is working, but I can't seem to get the preview from the previous image to show up where it should, by pulling the existing image from the database.
What happens is that it will only show the new image, after it has been uploaded via drag and drop but not the previous one stored in the database. I'm pulling the url of the previous image with the const "testing" and I can log it and it will show inside the console but it will not show when I use it in the setFileList const. What am I missing here?
export function FacilityUpdate() {
const navigate = useNavigate()
const { id } = useParams()
const [facility, setFacility] = useState(null)
const accessToken = useSelector((state) => state.tokens.value.accessToken);
const [loadingFacility, setLoadingFacility] = useState(false)
const [loading, setLoading] = useState(false)
const dispatch = useDispatch();
useEffect(() => {
if (facility && !facility.is_owner) {
navigate('/facilities')
}
return () => null
})
useEffect(() => {
setLoadingFacility(true)
function fetchFacility() {
axios.get(API.facilities.retrieve(id), {
headers: {
"Authorization": `Bearer ${accessToken}`
},
withCredentials: true,
})
.then(res => {
setFacility(res.data)
})
.finally(() => {
setLoadingFacility(false)
})
}
fetchFacility()
return () => null
}, [id, accessToken])
const testing = facility && (facility.mainimage)
console.log(testing)
const [fileList, setFileList] = useState([
{
uid: '-1',
name: testing,
status: 'done',
//This is where the preview image gets loaded from the database:
url: testing,
},
]);
const onUploadDraggerChange = ({ fileList: newFileList, file: resp }) => {
setFileList(newFileList);
if (!resp || !resp.response || !resp.response.mainimage) {
return;
}
message.success("Updated facility picture")
};
const uploadDraggerrops = {
name: 'mainimage',
action: API.facilities.update(id),
method: 'PATCH',
listType: "picture-card",
maxCount: 1,
onChange: onUploadDraggerChange,
fileList: fileList,
headers: {
"Authorization": `Bearer ${accessToken}`
},
withCredentials: true,
};

The problem with your code might come from this line on onUploadDraggerChange:
setFileList(newFileList);
Before updating the state of fileList, fileList is an array with an element that contains that previous picture. When you call onUploadDraggerChange you are erasing the stored content and replacing it with the new one. Maybe you want to push it to add to the array?
setFileList([...fileList, newFileList]);
This way, the first element is the one fetched and the consequent ones from the draggerUpload.
Any case, it looks like the structure of your state should look like
const [facility, setFacility] = useState(null)
const [fileList, setFileList] = useState([]);
useEffect(() => {
if (facility && !facility.is_owner) {
navigate('/facilities')
}
return () => null
})
useEffect(() => {
setLoadingFacility(true)
function fetchFacility() {
axios.get(API.facilities.retrieve(id), {
headers: {"Authorization": `Bearer ${accessToken}`},
withCredentials: true,
})
.then(res => {
setFacility(res.data)
res && (res.mainimage) {
setFileList([...filelist, {
uid: 'some-random-id',
name: testing,
status: 'done',Ï
url: res.mainimage
}])
})
.finally(() => {
setLoadingFacility(false)
})
}
fetchFacility()
return () => null
}, [id, accessToken])

Related

I am using provide/inject to pass the data within components , I've this function using compute, I am trying to run and pass it's result in provide

I have 4 functions, for 1st three functions, I can send the data in provide. For 4th function(
getViewApplicationDetails
), I am trying to fetch api and get application name, now I want that in mounted because, I want the application name as soon as component is rendered so I am trying to execute it in mounted but when I call the it, it's giving me error. Initially application name is empty and it should have the current application name when I fetch the api, the same application name will be used in provide and then I can use that in inject and then in any other component.
import { computed, inject, onMounted, provide, reactive } from "vue";
export const initStore = () => {
onMounted(()=>{
this.getViewApplicationDetails()
});
// State
const state = reactive({
name: "Bob Day",
email: "bob#martianmovers.com",
applicationName: "",
breadcrumbsData: [
{
name: "Home",
text: 'Home',
disabled: false,
href: '/'
}
]
});
// Getters
const getUsername = computed(() => state.name);
const getEmail = computed(() => console.log("state.email",state.email));
const getBreadcrumbsData=computed(()=>state.breadcrumbsData)
console.log("state.applicationName",state.applicationName)
//this is the temporary function
const getApplicationName=computed(()=>state.applicationName)
const getViewApplicationDetails=computed(()=> {
var viewApplicationDetailsParams = {
applicationId: this.$route.query.applicationId,
applicationStatus:this.$route.query.appStatus,
authType: "api",
clientId: process.env.VUE_APP_EXTERNAL_API_CLIENT_ID,
clientSecret: process.env.VUE_APP_EXTERNAL_API_CLIENT_SECRET
};
axios({
method: "post",
url: process.env.VUE_APP_BLUJ_BACKEND_URL + "/viewapplicationDefinition",
data: viewApplicationDetailsParams,
headers: {
"content-type": "application/json",
},
})
.then((response) =>{
this.viewDefinitionResponse = response.data.Definitions;
let applicationName = viewDefinitionResponse.application_display_name.en;
console.log("tyfgyhkjlfhgjklnm",applicationName)
setApplicationName(applicationName)
})
.catch((error) => {
console.log("error", error);
});
});
getViewApplicationDetails()
// Mutations
const setUsername = (name) => {
state.name = name;
};
const setEmail = (email) => {
state.email = email;
};
const setBreadCrumbsData=(breadcrumbsData)=>{
state.breadcrumbsData=breadcrumbsData;
}
const setApplicationName=(appName)=>{
state.applicationName=appName
}
// Actions
const updateUsername = (name) => {
setUsername(name);
};
const updateEmail = (email) => {
setEmail(email);
};
provide("getUsername", getUsername);
provide("getEmail", getEmail);
provide("updateUsername", updateUsername);
provide("updateEmail", updateEmail);
provide("getViewApplicationDetails", getViewApplicationDetails);
provide("getApplicationName", getApplicationName);
provide("getBreadcrumbsData", getBreadcrumbsData);
};
export const useStore = () => ({
getUsername: inject("getUsername"),
getEmail: inject("getEmail"),
updateUsername: inject("updateUsername"),
updateEmail: inject("updateEmail"),
viewApplicationDetails: inject("getViewApplicationDetails"),
getBreadcrumbsData: inject("getBreadcrumbsData"),
getApplicationName: inject("getApplicationName")
});
This is the code snippet.
const getUsername = computed(() => state.name);
const getEmail = computed(() => console.log("state.email",state.email));
const getBreadcrumbsData=computed(()=>state.breadcrumbsData)
I am getting data for this, but for getViewApplicationDetails, it's not working. While hovering over rest of the functions, it is showing "const getUsername: ComputedRef", like this. But, for getViewApplicationDetails, it shows "const getViewApplicationDetails: ComputedRef", this. I think it is not taking it as function or something. Error image is in the link.enter image description here

What is the best way to call a function and render a child component onClick in React?

I have the below code, I want to call a function and render a child component onCLick. What is the best way to achieve this?
import AddOrder from './AddOrder'
return (
<Button onClick={handleCheckout}>Checkout</Button>
)
const handleCheckout = () => {
<AddOrder />
fetch("http://localhost:5000/create-checkout-session", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
items: data?.getUser ? data.getUser.cart : cart,
email: currentUser ? currentUser.email : undefined,
}),
})
.then(async (res) => {
if (res.ok) return res.json();
const json = await res.json();
return await Promise.reject(json);
})
.then(({ url }) => {
window.location = url;
})
.catch((e) => {
console.error(e.error);
});
};
I tried making a new function called handleAll and adding it like this:
function handleAll(){
handleCheckout()
<AddOrder />
}
AddOrder.js:
function AddOrder() {
const d = new Date();
let text = d.toString();
const { currentUser } = useContext(AuthContext);
const { data, loading, error } = useQuery(queries.GET_USER_BY_ID, {
fetchPolicy: "cache-and-network",
variables: {
id: currentUser.uid
},
});
const [addOrder] = useMutation(queries.ADD_ORDER);
useEffect(() => {
console.log('hi')
})
if(error) {
return <h1> error</h1>;
}
if(loading) {
return <h1> loading</h1>;
}
if (data){
let newCart = []
for(let i=0; i< data.getUser.cart.length; i++){
newCart.push({quantity: data.getUser.cart[i].quantity, _id: data.getUser.cart[i]._id})
}
console.log(newCart)
addOrder({
variables: {
userId: currentUser.uid, status: 'ordered', createdAt: text, products: newCart
}
});
console.log("hello")
}
}
export default AddOrder;
This did not work either. When I reload this it add 3 copies of the same order to the mongodb collection. What is the right way to do this?

My object is being logged and set in the front end of React, but it is not being saved in the database

I'm trying to pass in my One Rep Max object which is a variable of my Plan object, through my Plan object.
function FiveThreeOne(props) {
const history = useHistory();
const [user, setUser] = useState({});
const [orm, setOrm] = useState({
benchPressMax: '',
squatMax: '',
overHeadPressMax: '',
deadliftMax: '',
})
useEffect(() => {
const params = {
id: localStorage.getItem("loggedInUser"),
}; console.log(localStorage)
axios.get(`http://localhost:8080/getUser/${params.id}`, {
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
setUser(response.data);
}).catch((error) => {
console.log('error in getting account')
});
}, []);
const ormChangeHandler = (event) => {
const name = event.target.name;
const value = event.target.value;
const tempOrm = { ...orm };
tempOrm[name] = value;
setOrm(tempOrm)
console.log(orm)
}
/*const ormSubmitHandler = () => {
user.plan.orm = Object.assign({orm})
axios.post(`http://localhost:8080/addORM`, orm, {
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
setOrm(response.data)
})
}*/
const [plan, setPlan] = useState({
name: 'Five Three One',
ormId: orm,
})
const planSubmitHandler = () => {
plan.ormId = Object.assign({orm})
console.log(plan)
axios.post(`http://localhost:8080/createPlan/${user.id}`, plan, {
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
setPlan(response.data)
history.push('/user-profile')
})
}
One of my change handlers:
<input type="number" name="benchPressMax" value={orm.benchPressMax} id="inputBenchPressMax" placeholder='Enter bench' onChange={ormChangeHandler}/>
<table className='workout-table' id='workout-list'>
<thead id='workout-list'>
My submit handler:
<div><button className='workoutList-button' onClick={planSubmitHandler}>Add</button></div>
The plan object is being passed and saved, but the ORM is being set to null in my back end. The conlog shows that the object is populated.
Front end console log:
{name: 'Five Three One', ormId: {…}}
name: "Five Three One"
ormId:
orm:
benchPressMax: "1"
deadliftMax: "1"
overHeadPressMax: "1"
squatMax: "1"
Back end:
public Plan createPlan(Long id, Plan plan) {
User account = userService.getAccount(id);
Plan newPlan = plan;
plan.setPlanStart(LocalDate.now());
account.getPlan().add(newPlan);
OneRepMax planORM = plan.getOrmId();
System.out.println(planORM.getBenchPressMax());
ormRepo.save(planORM);
planRepo.save(newPlan);
userRepo.save(account);
return newPlan;
}
The benchpressMax shows null in my eclipse console.

How to filter data in two different state when promise.all resolved?

I send two requests to get
1- my services
2- admin services
when i got the response i set the state "myService, admin".
now admin services that contain my services.
So i want to filter if my services in admin service delete admin service from the array.
so I'm trying to using new Set but not works maybe i miss something
and another issue i use Promise.all to await the two request, but when I log the state there I got the initial state 'empty'
sample of data "my services and admin"
[
//my service
{
"id": 1,
"img": ".....",
"name": "service 1"
},
{
"id": 2,
"img": ".....",
"name": "service 2"
},
{
"id": 3,
"img": ".....",
"name": "service 3"
},
//admin service
{
"id": 1,
"img": ".....",
"name": "service 1"
},
]
Code snippet
const [myServices, setMyServices] = useState([]);
const [adminServices, setAdminServices] = useState([]);
const [allService, setAllService] = useState([]);
useEffect(() => {
const getAdminServices = async () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
Api.post('/admin/service', {}, {headers})
.then((res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('admin', serviceModified);
setAdminServices(serviceModified);
})
.catch((err) => console.log('err', err));
};
const getMyServices = async () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
Api.post('/vendor/service', {}, {headers})
.then((res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('mine', serviceModified);
setMyServices(serviceModified);
setSelectedService(serviceModified); // for checkbox
})
.catch((err) => console.log('err', err));
};
Promise.all([getMyServices(), getAdminServices()]).then(() => {
let allServices = [...myServices, ...adminServices]; // log empty!
let uniq = [...new Set(allServices)];
console.log(myServices);
console.log('filtered', uniq);
console.log('here i want to filter the data', allServices);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
UI
<FlatList
data={allService}
keyExtractor={(item, index) => String(index)}
renderItem={renderMyServices}
/>
First of all you should return the promises from getMyServices and getAdminServices.
Also, setting state in react is async. So the updates to myServices and adminServices are not guaranteed to be reflected by the time you try using them. I suggest you return the results from the promises and use those values instead of the state.
Example:
const [myServices, setMyServices] = useState([]);
const [adminServices, setAdminServices] = useState([]);
const [allService, setAllService] = useState([]);
useEffect(() => {
const getAdminServices = () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
return Api.post('/admin/service', {}, {headers})
.then((res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('admin', serviceModified);
return serviceModified;
})
.catch((err) => console.log('err', err));
};
const getMyServices = () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
return Api.post('/vendor/service', {}, {headers})
.then((res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('mine', serviceModified);
return serviceModified;
})
.catch((err) => console.log('err', err));
};
Promise.all([getMyServices(), getAdminServices()]).then(([myServices, adminServices]) => {
// set state and do stuff
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
I think you are using promises.all wrongly.
Ideally promises.all can await only if all the functions return you promises, but in your case, you are returning undefined.
Hence even before the API call is responding Promises.all will complete the execution and then is executed as well.
you can restructure your code to something like below,
(still, I see a lot of room for refactoring).
const [myServices, setMyServices] = useState([]);
const [adminServices, setAdminServices] = useState([]);
const [allService, setAllService] = useState([]);
useEffect(() => {
const getAdminServices = async () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
return Api.post('/admin/service', {}, {headers});
};
const setMyServices = (res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('mine', serviceModified);
setMyServices(serviceModified);
setSelectedService(serviceModified); // for checkbox
return serviceModified;
}
const setAdminServices = (res) => {
let {services} = res.data;
let serviceModified = [];
services.map((service) => {
serviceModified.push({
id: service.id,
name: service.service_name,
img: DOMAIN_URL + service.images_show[0]?.image,
});
});
console.log('admin', serviceModified);
setAdminServices(serviceModified);
return serviceModified;
}
const getMyServices = async () => {
let AuthStr = `Bearer ${token}`;
const headers = {
Authorization: AuthStr,
Accept: 'application/json',
};
return Api.post('/vendor/service', {}, {headers});
};
Promise.all([getMyServices(), getAdminServices()]).then((data) => {
console.log(data); // will have [myServiceResponse, adminServiceReponse];
const myServices = setMyServices(data[0]);
const adminServices = setAdminServices(data[1]);
let allServices = [...myServices, ...adminServices]; // log empty!
// set doesn't work this way, use `uniq` utility function from `lodash` or develop a custom one if required.
let uniq = [...new Set(allServices)];
console.log(myServices);
console.log('filtered', uniq);
console.log('here i want to filter the data', allServices);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Moving into Spotify array

I'm trying to use Spotify API and to move into the Arrays.
const App = () => {
const [isLoading, setIsLoading] = useState(true);
const [dataSource, setDataSource] = useState();
useEffect(() => {
return fetch("https://api.spotify.com/v1/me/albums?offset=0&limit=5", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization:
"Bearer AUTH CODE "
}
})
.then(response => response.json())
.then(responseJson => {
setIsLoading(false);
// console.log(responseJson);
// let result = Object.values(responseJson); // if I want to convert it in array
let result = responseJson
setDataSource(result);
});
}, []);
console.log(dataSource);
and I get an object
{href: "https://api.spotify.com/v1/me/albums?o`enter code here`ffset=0&limit=5", items: Array(5) ...}
I would like to go into items but when i do
console.log(dataSource.items);
or
console.log(dataSource.items[1]);
I get
Cannot read property 'items' of undefined
Any idea?
Where is my mistake?
The dataSource state is by default undefined, you need to change the default value to have items property. The fetch is handling the then asynchronously so the data will arrive few milliseconds later and in that time the code tries to access items property which is missing.
You can try to initialize differently, like the following:
const [dataSource, setDataSource] = useState({ items: [] });
I hope this helps!

Categories

Resources