I need to call Get method API. While select the dropdown value. If I select dropdown options="A" value=1 that value will set to API URL "http://localhost:12345/api/GetProfile/Get_MyPostDetails?id=${inputValue}". Please share any idea in react js. Dropdown values are set manually.
This one I tried
import React, { useState } from 'react';
import AsyncSelect from 'react-select/async';
function App() {
const [inputValue, setValue] = useState('');
const [selectedValue, setSelectedValue] = useState(null);
// handle input change event
const handleInputChange = value => {
setValue(value);
};
// handle selection
const handleChange = value => {
setSelectedValue(value);
}
const category=() =>
[
{
value:1,
label:"2017"
},
{
value:2,
label:"2018"
},
{
value:3,
label:"2019"
},
{
value:4,
label:"2020"
},
{
value:5,
label:"2021"
},
{
value:6,
label:"2022"
}
];
// load options using API call
const loadOptions = (inputValue) => {
let user = JSON.parse(localStorage.getItem('user'));
const accessToken=user;
fetch(`http://localhost:12345/api/GetProfile/Get_MyPostDetails?id=${inputValue}`, {
method: 'get',
headers:{
Accept: 'application/json',
Authorization: "Bearer " +accessToken
},
}).then(res => res.json());
};
return (
<div className="App">
<h3>React-Select Async Dropdown - Clue Mediator</h3>
<pre>Input Value: "{inputValue}"</pre>
<AsyncSelect
cacheOptions
defaultOptions
value={selectedValue}
options={category}
loadOptions={loadOptions}
onInputChange={handleInputChange}
onChange={handleChange}
/>
<pre>Selected Value: {JSON.stringify(selectedValue || [{}], null, 2)}</pre>
</div>
);
}
export default App;
I tried this one but it didn't work because I need get array of objects9multiple records) it display single records and also it display the option value from API URL I want to add it manually
Thank you in advance
Related
I have 2 Api requests, one of them hangs on the child - from it, when I click on the picture, I get the track key and give it to the parent in the second Api request as a parameter so that it displays the information I need. But when I output this to the console, I get an empty message =(
result console.log
CHILD
import React from 'react'
import { AppContext } from '../MainContent'
import TrackTranding from './TrackTranding'
const ContentTrending = ({ onClick }) => {
const { articles, setArticles } = React.useContext(AppContext)
const handleClick = (e) => {
e.preventDefault();
onClick(articles[e.target.dataset.attr].key) // get key from first api
}
return (
<div className="main__content-trending">
<p>Tranding right now</p>
<div className="noflex-oneblock">
<div className="main__content-trending-artist-title ">
{
articles.map((tracks, index) => {
return (
<div className='one' key={tracks.key}
onClick={handleClick}
>
<TrackTranding
tracks={tracks}
index={index}
/>
<audio src="#" id="audioTrack"></audio>
</div>
)
})
}
</div>
</div>
</div>
)
}
export default ContentTrending
PARENT
import axios from 'axios'
import React from 'react'
import MainContentBg from './MainBcg/ContentBg'
import MainContentTitle from './MainTitle/ContentTitle'
import ContentTrending from './MainTrending/ContentTrending'
export const AppContext = React.createContext()
const MainContent = () => {
const [articles, setArticles] = React.useState([])
const [detailse, setDetailse] = React.useState([])
const [name, setName] = React.useState('');
const handleClick = (name) => {
setName(name)
console.log(detailse) // --------------------------- error =()
}
const fetchData = () => {
const chart = {
method: 'GET',
url: 'https://shazam.p.rapidapi.com/charts/track',
params: { locale: 'en-US', pageSize: '20', startFrom: '0' },
headers: {
'X-RapidAPI-Key': '10eb9d1c65msh1029069c658be40p1197a5jsne7f1ee8c9f88',
'X-RapidAPI-Host': 'shazam.p.rapidapi.com'
}
};
axios.request(chart).then(data => {
const tracksApi = data.data.tracks
setArticles(tracksApi)
})
const details = {
method: 'GET',
url: 'https://shazam.p.rapidapi.com/songs/get-details',
params: { key: { name }, locale: 'en-US' }, // ---------------------------------- param
headers: {
'X-RapidAPI-Key': '10eb9d1c65msh1029069c658be40p1197a5jsne7f1ee8c9f88',
'X-RapidAPI-Host': 'shazam.p.rapidapi.com'
}
};
axios.request(details).then(data => {
const tracksDetails = data.data
setDetailse(tracksDetails)
})
}
React.useEffect(() => {
fetchData()
}, []);
return (
<main className="main">
<div className="main__content">
<AppContext.Provider value={{ articles, setArticles }}>
<MainContentTitle />
<MainContentBg />
<ContentTrending onClick={handleClick} />
</AppContext.Provider>
</div>
</main>
)
}
export default MainContent
Currently you call fetchData when the component first mounts the name state is set to an empty string "".
React.useEffect(() => {
fetchData();
}, []);
Which you're passing in the details so essentially the object looks like this:
const details = {
method: "GET",
url: "https://shazam.p.rapidapi.com/songs/get-details",
params: { key: { name: "" }, locale: "en-US" }, // notice the empty string
headers: {
"X-RapidAPI-Key": "10eb9d1c65msh1029069c658be40p1197a5jsne7f1ee8c9f88",
"X-RapidAPI-Host": "shazam.p.rapidapi.com",
},
};
Instead what you can do is trigger the useEffect when the name changes. Which will now have the updated name from the handleClick from the Child.
React.useEffect(() => {
fetchData();
}, [name]);
You probably want to change, currently you're setting the key to a object with another prop called name.
params: { key: { name }, locale: 'en-US' }
to, this will make sure the key prop has the value from name
params: { key: name, locale: 'en-US' }
Currently following a slightly older tutorial, but learning using React 18 -- trying to update the text area in a notes app
It looks like when I type, a character appears and then immediately is deleted automatically
Can anyone confirm if I might be missing a detail here?
for reference if familiar with the project at time 1:37:03 : https://www.youtube.com/watch?v=6fM3ueN9nYM&t=377s
import React, {useState, useEffect} from 'react'
import notes from '../assets/data'
import { useParams } from 'react-router-dom';
import { Link } from 'react-router-dom'
import { ReactComponent as ArrowLeft } from '../assets/arrow-left.svg'
const NotePage = ( history ) => {
const {id} = useParams();
// let note = notes.find(note => note.id===Number(id))
// console.log(id)
let [note, setNote] = useState(null)
useEffect(() => {
getNote()
}, [{id}])
let getNote = async () => {
let response = await fetch(`http://localhost:8000/notes/${id}`)
let data = await response.json()
setNote(data)
}
// let updateNote = async () => {
// await fetch(`http://localhost:8000/notes/${id}`, {
// method: 'PUT',
// headers: {
// 'Content-Type': 'application/json'
// },
// body: JSON.stringify({...note, 'updated':new Date()})
// })
// }
// let handleSubmit = () => {
// updateNote()
// history.push('/')
// }
return (
<div className="note">
<div className="note-header">
<h3>
<Link to="/">
<ArrowLeft /*onClick={handleSubmit}*/ />
</Link>
</h3>
</div>
<textarea onChange={(e) => {
setNote({...note, 'body': e.target.value}) }}
value={note?.body}>
</textarea>
</div>
)
}
export default NotePage
Your value in the useEffect dependency array is incorrect and causing getNote to be called every time you make changes in the textArea. Every time getNote is called, it's resetting the note state back to whataver is being received by getNote. Which in your case is probably a blank note
Change this :
useEffect(() => {
getNote();
}, [{ id }]);
To this:
useEffect(() => {
getNote();
}, [id]);
I have a page users.jsx (parent) and a component DialogEditUser.jsx (child) and i would like to pass a specific data of a user that is located in parent to child by it's id (using find method)
This passed data should be loaded to its input in react modal as a value.
users.jsx Code:
import React, { useState, useEffect } from 'react'
import DialogAddUser from 'src/components/DialogAddUser'
import { getUsers} from 'src/Service/api'
const Typography = () => {
const [users, setUsers] = useState([])
useEffect(() => {
getAllUsers()
}, [])
const deleteUserData = async (id) => {
setConfirmDialog({
...setConfirmDialog,
isOpen: false,
})
await deleteUser(id)
getAllUsers()
setNotify({
isOpen: true,
message: 'Article Deleted Successfully.',
type: 'error',
})
}
const getAllUsers = async () => {
let response = await getUsers()
setUsers(response.data)
console.log(response.data)
}
return ( //... )
DialogEditUsers.jsx Code:
import { useEffect, useState } from 'react'
import { getUsers, editUser } from '../Service/api'
const initialValue = {
id: '',
code: '',
article: '',
price: '',
vat: '',
status: '',
company_id: '',
}
export default function DialogAddUser() {
const [user, setUser] = useState(initialValue)
const { code, article, price, vat, status, company_id } = user
const normalize = (v) => ({
code: v.code,
article: v.article,
price: Number(v.price),
vat: Number(v.vat),
status: Number(v.status),
company_id: Number(v.company_id),
})
useEffect(() => {
loadUserDetails()
}, [])
const loadUserDetails = async () => {
const response = await getUsers(id)
console.log('loading user details ', response)
setUser(response.data.find((x) => x.id == id))
}
const editUserDetails = async () => {
const response = await editUser(id, normalize(user))
console.log('Edit user details ', response)
}
const onValueChange = (e) => {
console.log(e.target.value)
setUser({ ...user, [e.target.name]: e.target.value })
}
return (
<>
<CModal
visible={visible}
onClose={() => setVisible(false)}
backdrop={'static'}
keyboard={false}
portal={false}
>
<CModalHeader>
<CModalTitle>Edit Article:</CModalTitle>
</CModalHeader>
<CModalBody>
<CForm>
<CFormInput
type="text"
id="exampleFormControlInput1"
label="Code :"
placeholder="Enter Code"
text=" "
aria-describedby="exampleFormControlInputHelpInline"
onChange={(e) => onValueChange(e)}
value={code}
name="code"
/>
<CFormInput
type="text"
id="exampleFormControlInput2"
label="Article :"
placeholder="Enter Article"
text=" "
aria-describedby="exampleFormControlInputHelpInline"
onChange={(e) => onValueChange(e)}
value={article}
name="article"
/>
//...the rest of inputs...
api.js Code:
import axios from 'axios'
const baseURL = 'https://api.factarni.tn/article'
const token =
'eyJhbGciOiJSUzI1NiIsImtpZCI6IjIxZTZjMGM2YjRlMzA5NTI0N2MwNjgwMDAwZTFiNDMxODIzODZkNTAiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiZmFraHJpIGtyYWllbSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BSXRidm1uMS12dWJJcHNxTURKMkNTcDhVcTlmU3I1LUI1T3Y3RHY2SFRNMT1zMTMzNyIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9mYWN0YXJuaSIsImF1ZCI6ImZhY3Rhcm5pIiwiYXV0aF90aW1lIjoxNjYzNzY3ODk5LCJ1c2VyX2lkIjoiaWhqM0JWM0hIRFhpVnUwdmpzV3ZidjMyRDdMMiIsInN1YiI6ImloajNCVjNISERYaVZ1MHZqc1d2YnYzMkQ3TDIiLCJpYXQiOjE2NjM3Njc4OTksImV4cCI6MTY2Mzc3MTQ5OSwiZW1haWwiOiJmYWtocmlpLmtyYWllbUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjEwODU1MTA3MjAwODIwNjMxMjI0NCJdLCJlbWFpbCI6WyJmYWtocmlpLmtyYWllbUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.bvRTxHfPtJrQjF2BjXqhs7ji738kma55LMFVRb8jkeraWP-JRBi-LRPa0d7OR_-BPwCGuRBXIb6980_PP8wjhBeDdB5B77GujiGn3nUvpPOFeIaM0L7muw1NKo4YCtS3v6ifuywypTbL3_5x3SBFZEH-QV0sp5DAzaA-P3Fn8AwP66o3cUPHGengGpZNsfkJ0FYcqzH-xpyKVVWV'
//i dont mind sharing this token, it's for you to test this code if you need.
const config = { headers: { Authorization: `Bearer ${token}` } }
export const getUsers = async (id) => {
id = id || ''
try {
return await axios.get(`${baseURL}`, config)
} catch (error) {
console.log('Error while calling getArticles api ', error)
}
}
export const editUser = async (id, user) => {
return await axios.put(`${baseURL}/${id}`, user, config)
}
The only node error i'm getting in terminal using this code above (because i dont know how to pass the proper id of specified user) is:
src\components\DialogEditUser.jsx
Line 45:37: 'id' is not defined no-undef
Line 47:47: 'id' is not defined no-undef
Line 51:37: 'id' is not defined no-undef
For better explanation the problem (i dont know how to use online snippets sorry):
So what i'm expecting is: When i click on Edit button, i should get a modal with form that are filled with user data (code, article, price, vat, status and company_id) in each input of the form as value, just like this gif below:
Also, console.log(response.data) in users page shows this:
few days back i also faced the same issue. Solution for me is to create state in parent component and pass state to child. Example for it-
Parent Class
const parent= ()=>{
const [name, setName]= useState('')
const [password, setPassword]= useState('')
return(
<Child setName={setName} setPassword={setPassword} />
)
}
Child Class
const Child = ({setPassword,setName})=>{
return(
<div>
<input type="text" placeholder="Enter Name" onChange={(e)=>setPassword(e.target.value)} />
<input type="text" placeholder="Enter Name" onChange={(e)=>setPassword(e.target.value)} />
</div>
)
}
Hope my answer will help you to solve your problem, if you still facing issue, lemme know i will help you.
In users.jsx, pass props of (user.id):
<DialogEditArticle props={user.id} />
Then, in DialogEditArticle.jsx, create a new data and call in it props:
const DialogEditArticle = (data) => {
console.log(data.props)
Now console.dev, you will get all the ids of user in database (because button edit is inside map function).
Result:
I have a material-ui LinearDeterminate progress bar, and I would like to pass on how far along the upload is.
const LinearDeterminate = ({ uploadPercentage, setuploadPercentage }) => {
const classes = useStyles();
const [uploadPercentage, setuploadPercentage] = useState("");
console.log(uploadPercentage);
return (
<div className={classes.root}>
<LinearProgress variant="determinate" value={uploadPercentage} />
</div>
);
};
...
<UploadInput
path={`customer_creatives/assets/${customer_id}/${new Date().getTime()}`}
onChange={(value) =>
updateFieldHandler("link_to_assets")({ target: { value } })
}
value={submissionData["link_to_assets"] || ""}
label="Link to Assets"
sublabel="*Zip files before uploading"
isImage={false}
/>
<LinearDeterminate />
...
UploadInput is a custom input component that links to DropZone (Where the upload happens)
import React, { useState } from "react";
import ReactDropzone from "react-dropzone";
import axios from "axios";
import { noop } from "lodash";
import HelpDialog from "components/HelpDialog";
import { API_URL } from "config";
const Dropzone = ({
path,
onChange = noop,
children,
multiple = false,
maxSize,
sizeHelper,
...props
}) => {
const [url, setUrl] = useState("");
const [loading, setLoading] = useState("");
const [uploadPercentage, setuploadPercentage] = useState("");
const [sizeHelperOpen, setSizeHelperOpen] = useState(false);
const onDrop = ([file]) => {
const contentType = file.type; // eg. image/jpeg or image/svg+xml
console.log(file);
if (maxSize && maxSize < file.size) {
setSizeHelperOpen(true);
return;
}
const generatePutUrl = `${API_URL}/generate-put-url`;
const generateGetUrl = `${API_URL}/generate-get-url`;
const options = {
onUploadProgress: (progressEvent) => {
//console.log("progressEvent.loaded " + progressEvent.loaded)
//console.log("progressEvent.total " + progressEvent.total)
let percent = Math.round(
(progressEvent.loaded / progressEvent.total) * 100
);
setuploadPercentage({
uploadPercentage: percent,
});
console.log(uploadPercentage);
},
params: {
Key: path,
ContentType: contentType,
},
headers: {
"Content-Type": contentType,
},
};
setUrl(URL.createObjectURL(file));
setLoading(true);
axios.get(generatePutUrl, options).then((res) => {
const {
data: { putURL },
} = res;
axios
.put(putURL, file, options)
.then(() => {
axios.get(generateGetUrl, options).then((res) => {
const { data: getURL } = res;
onChange(getURL);
setLoading(false);
});
})
.catch(() => {
setLoading(false);
});
});
};
return (
<ReactDropzone onDrop={onDrop} multiple={multiple} {...props}>
{({ getRootProps, getInputProps }) => (
<>
<div {...getRootProps()}>
<input {...getInputProps()} />
{children({ url, loading })}
</div>
<HelpDialog
open={sizeHelperOpen}
onClose={() => setSizeHelperOpen(false)}
>
{sizeHelper}
</HelpDialog>
</>
)}
</ReactDropzone>
);
};
export default Dropzone;
I'm trying to get the results from the onUploadProgress function into my progress bar. Can I use a custom hook for that? My problem with that is Dropzone already has an export. Thanks for any advice!
It looks as simple as lifting the state up. You actually already have the { uploadPercentage, setuploadPercentage } props on the LinearDeterminate component. Just put that state in the common parent of the UploadInput and the LinearDeterminate components, and then keep passing down the handler to the DropZone component
Remove the state from the LinearDeterminate component
const LinearDeterminate = ({ uploadPercentage }) => {
const classes = useStyles();
return (
<div className={classes.root}>
<LinearProgress variant="determinate" value={uploadPercentage} />
</div>
);
};
Move it to the common parent
const [uploadPercentage, setuploadPercentage] = useState("");
...
<UploadInput
path={`customer_creatives/assets/${customer_id}/${new Date().getTime()}`}
onChange={(value) =>
updateFieldHandler("link_to_assets")({ target: { value } })
}
value={submissionData["link_to_assets"] || ""}
label="Link to Assets"
sublabel="*Zip files before uploading"
isImage={false}
setuploadPercentage={setuploadPercentage}
/>
<LinearDeterminate uploadPercentage={uploadPercentage}/>
...
UploadInput component
const UploadInput = ({ setuploadPercentage, ...allOtherCrazyProps }) => {
...
return (
<DropZone setuploadPercentage={setuploadPercentage} {...moreCrazyProps} />
);
};
And finally, in the DropZone
const Dropzone = ({
path,
onChange = noop,
children,
multiple = false,
maxSize,
sizeHelper,
setuploadPercentage, // this is the new prop
...props
}) => {
...
const options = {
onUploadProgress: (progressEvent) => {
...
setuploadPercentage(percent); // is a string?
console.log(uploadPercentage);
},
...
};
...
};
If you find it cumbersome passing the handler all the way down, you could use a Context to manage that state, but anywhere you use the UserInput you'll need to wrap it on the context provider.
I'd also say to move all the uploading logic and build something similar to downshift-js: a hook that returns all necessary props to turn an element into a droppable uploader, but you already depend on the ReactDropzone component, so I don't think can be done unless you try this other pattern https://blog.bitsrc.io/new-react-design-pattern-return-component-from-hooks-79215c3eac00
You can set the upload precent value after each axios successful call.
axios.get(generatePutUrl, options).then(res => {
const {
data: { putURL }
} = res;
/* Set precent to 33% here */
axios
.put(putURL, file, options)
.then(() => {
/* Set precent to 66% */
axios.get(generateGetUrl, options).then(res => {
/* Set precent to 99% here */
const { data: getURL } = res;
onChange(getURL);
setLoading(false);
});
})
.catch(() => {
setLoading(false);
});
});
Hope that helps.
I am trying to set the selected value of my react-select from useState(). I get my data from a API that I call in useEffect(). I have the data to populate the select options which is 'brandOptions ' below but after hit my API I am trying ty set my to what comes back from API = > setSelectedBrandOption({ label: data[0].brandPreference, value: data[0].brandPreference}) ... what I am I dong wrong? Right now the dropdown doesn't change.
My data from API comes back like this:
data: [
0: { brandPreference: "Huggies", currentSize: 2, firstName: "Roman" }
]
Here is my code:
import React, { useState, useContext, useEffect } from 'react';
import Select from 'react-select';
import { UserContext } from '../context/UserContext';
import './Settings.css';
const brandOptions = [
{ value: 'Huggies', label: 'Huggies' },
{ value: 'Kirkland', label: 'Kirkland' },
{ value: 'Pampers', label: 'Pampers' },
{ value: 'Parents', label: "Parent's Choice" },
{ value: 'Up', label: 'Up & Up' },
];
const Settings = () => {
const [kidsData, setKidsData] = useState([]);
const { user, setUser } = useContext(UserContext);
const [selectedBrandOption, setSelectedBrandOption] = useState({});
useEffect(() => {
const user_ID = user.user._id;
const url = `/api/kids/${user_ID}`;
const getKids = async () => {
try {
const headers = {
'Content-Type': 'application/json',
'x-auth-token': user.jwt,
};
const res = await fetch(url, {
method: 'GET',
headers: headers,
});
const data = await res.json();
setKidsData(data)
setSelectedBrandOption({
label: data[0].brandPreference,
value: data[0].brandPreference,
});
} catch (error) {
console.log(error)
}
}
getKids();
}, [])
return (
<section>
<Select
onChange={setSelectedBrandOption}
options={brandOptions}
placeholder={'Select Brand Preference'}
/>
</section>
);
};
export default Settings;
I would try two things:
1- Try setting the defaultValue prop in the Select component after the API request is made
2- Switch to an async approach using AsyncSelect as it is exposed in the following issue: https://github.com/JedWatson/react-select/issues/2877