how to fetch data according id/slug in ReactJS? - javascript

what i am trying to do is fetching the data according to category id/slug. for e.g i have two categories(brown, black) as you can see below. how to fetch blog_set data according to category id/slug ?
i am probably new to ReactJs. it would be great if anyone could help me out what i am trying to do is. thank you so much in advance.
endpoint-url : http://localhost:8000/api/category
api-data:
[
{
"id": 1,
"title": "brown",
"slug": "brown",
"image": "http://localhost:8000/media/category/bg_1.jpg",
"description": "",
"created_on": "2020-05-08T15:21:02Z",
"status": true,
"blog_set": [
{
"id": 6,
"url": "http://localhost:8000/api/blog_detail/test3",
"title": "test3",
"slug": "test3",
"image": "http://localhost:8000/media/blog/author.jpg",
"description": "test3",
"created_on": "2020-05-13T13:36:45Z",
"status": true,
"category": [
1
]
}
]
},
{
"id": 2,
"title": "black",
"slug": "black",
"image": "http://localhost:8000/media/category/image_7.jpg",
"description": "",
"created_on": "2020-05-08T17:14:43Z",
"status": true,
"blog_set": [
{
"id": 10,
"url": "http://localhost:8000/api/blog_detail/test3",
"title": "Hamid",
"slug": "test3",
"image": "http://localhost:8000/media/blog/person_2_2beHkt1.jpg",
"description": "test",
"created_on": "2020-05-13T14:59:30.855849Z",
"status": true,
"category": [
2
]
}
]
}
]
./src/Category.js
export default class App extends Component{
state = {
bloglist: [],
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
try {
const response = await fetch("http://localhost:8000/api/category");
const jsonResponse = await response.json();
this.setState({ bloglist: jsonResponse });
} catch (error) {
console.log(error);
}
};
render(){
{
const { bloglist } = this.state;
if (!bloglist) {
return (
<div>
<h1>loading...</h1>
</div>
);
}
return(
<div>
<h1>Category</h1>
{bloglist.map((bloglist) => (
<div>
<div class="col-md-12">
<div class="blog-entry animate d-md-flex">
<img src={bloglist.image} className="App-logo"/>
<h3 class="mb-2">{bloglist.title}</h3>
<h3 class="mb-2">{bloglist.blog_set.title}</h3>
</div>
</div>
</div>
))}
</div>
);
}
}
}

First check if the api supports fetching single category with id/slug. Then if you can call API with the id/slug from added to the fetch API call. If you want to show a separate page with the selected category you can enable a route with URL parameter with react-router-dom (https://reacttraining.com/react-router/web/example/url-params). And with this you will get the id/slug in the match prop which will be the this.props.history.match or with useParams() hooks. and then you can use it to call API with the selected id/slug.
Your UI URL will look like this. http://localhost:3000/category/:id and on browser it will look like this http://localhost:3000/category/black so when you call useParams() hook in your component it will be like {id} = useParams();
Now you can use this id to call the single selection API which might look like this <api_url>:<port>/category/black or <api_url>:<port>/category?slug=black

Pass query-params access deep properties
GET http://localhost:8000/api/category?slug=value
fetchData = async () => {
try {
const response = await fetch("http://localhost:8000/api/category?slug=value");
const jsonResponse = await response.json();
this.setState({ bloglist: jsonResponse });
} catch (error) {
console.log(error);
}
};

Related

Looping through array, fetching tweets and returning new reversed array javascript react

UPDATE: I have deployed the site for more context you can view it here https://conundrum-quest-rw-rebuild-web.onrender.com/
the public repo is here
https://github.com/wispyco/conundrum-quest-rw-rebuild
Note: the data on the live site is different but the initial load is loading the hero's on the wrong cards, you can compare the quest with subsequent heros on the home page and the returned data from my function below, you can scroll down to see the rendered cards.
You can see that if you click on a card it shows the correct heros on the single page.
I have the following quests data structure that I am looping through in a separate function and running a fetch to request some profile images from twitter.
[
{
"__typename": "Quest",
"id": 5,
"name": "How do we solve mental health related issues?",
"userId": 17,
"heros": [
{
"__typename": "Hero",
"name": "Anders Kitson",
"twitter": "anderskitson"
},
{
"__typename": "Hero",
"name": "ders",
"twitter": "derz_O"
}
]
},
{
"__typename": "Quest",
"id": 6,
"name": "How do we create a world where North Korea participates and collaborates with the rest of the World?",
"userId": 17,
"heros": [
{
"__typename": "Hero",
"name": "Crypto Dude",
"twitter": "phunk2243"
}
]
}
]
Here is my custom hook
const twitter = useFetchTwitterMultipleQuests(quests)
export const useFetchTwitterMultipleQuests = (twitterProfileManyQuests) => {
const [twitter, setTwitter] = useState([])
useEffect(() => {
twitterProfileManyQuests.forEach(async (twitterProfileMany, i) => {
const woop = twitterProfileMany.heros.map(async (twitterProfile) => {
const test = fetch(
`${window.location.origin}/.redwood/functions/twitter`,
{
method: 'POST',
body: JSON.stringify({ twitter: twitterProfile.twitter }),
}
)
.then(function (response) {
// The response is a Response instance.
// You parse the data into a useable format using `.json()`
console.log('test')
return response.json()
})
.then(function (data) {
return data.data.resultAwaited.data
})
const go = await test
return go
})
const june = await Promise.all(woop)
setTwitter((prevState) => {
return [...prevState, june]
})
})
}, [twitterProfileManyQuests])
const reversedTwitter = twitter.reverse()
return reversedTwitter
}
The problem is the reversedTwitter or twitter variable in the end sometimes is in the correct reversed order and sometimes not reversed, and I can't figure out why.
This is the correct order result
[
[
{
"username": "anderskitson",
"profile_image_url": "https://pbs.twimg.com/profile_images/1428160652237889539/I7ZiM_g8_normal.jpg",
"name": "▲nders on a quest 🜸 to see myself 🪞",
"id": "4633808432"
},
{
"profile_image_url": "https://pbs.twimg.com/profile_images/1496985668043436033/NoyLrUys_normal.jpg",
"name": "ders.eth",
"id": "1389695824934834181",
"username": "derz_O"
}
],
[
{
"username": "phunk2243",
"profile_image_url": "https://pbs.twimg.com/profile_images/1536485988767350784/cfP_sPSC_normal.jpg",
"name": "9999999333 (🅱️uilding 35 Phunks) 🔜",
"id": "1355005208259133442"
}
]
]
This is the incorrect order result
[
[
{
"name": "9999999333 (🅱️uilding 35 Phunks) 🔜",
"profile_image_url": "https://pbs.twimg.com/profile_images/1536485988767350784/cfP_sPSC_normal.jpg",
"username": "phunk2243",
"id": "1355005208259133442"
}
],
[
{
"username": "anderskitson",
"profile_image_url": "https://pbs.twimg.com/profile_images/1428160652237889539/I7ZiM_g8_normal.jpg",
"name": "▲nders on a quest 🜸 to see myself 🪞",
"id": "4633808432"
},
{
"username": "derz_O",
"profile_image_url": "https://pbs.twimg.com/profile_images/1496985668043436033/NoyLrUys_normal.jpg",
"name": "ders.eth",
"id": "1389695824934834181"
}
]
]
The reason this matters is how I am rendering the data. I am rendering a Quest from the quests data, then mapping over the heros in a quest which correspond to the twitter profiles.
See Here
{quests.map((quest, i) => (
<QuestCard key={quest.id}>
<Link to={routes.quest({ id: quest.id })} key={quest.id}>
<div>
<h3>{truncate(quest.name)}</h3>
{quest.heros.map((hero, index) => (
<React.Fragment key={hero.id}>
{twitter.length > 0 && twitter[i] && (
<span>
{hero.name}
<p>{twitter[i][index]?.name}</p>
<img
key={i}
src={twitter[i][index]?.profile_image_url}
alt={twitter[i][index]?.name}
/>
</span>
)}
</React.Fragment>
))}
</div>
</Link>
<div className="clear" />
</QuestCard>
))}
Any help would be greatly appreciated, most of what I have done works, but after about three refreshes the ordering breaks. Thanks
Fixed by using a custom service and a custom sdl in redwood instead of using a function and having to create a custom hook for rendering. This was recommended by the RW team from this article
https://redwoodjs.com/docs/how-to/using-a-third-party-api
And you can see my changes here
https://github.com/wispyco/conundrum-quest-rw-rebuild/pull/8/commits/41637813dd50be70e2e89372606c08e39618fa07

How to fetch json data in react?

useEffect(async () =>
{
const fetchData = async () =>
{
const result = await axios("")
setposts(result.data)
}
fetchData();
}, [])
Rendering :
posts.map(post => <li>{post.name}</li>)
Json File :
[
{
"id": 1,
"vendor": "Gap",
"name": "Men's Pullover Sweatshirt",
"image_src": ["https://cdn.shopify.com/s/files/1/0455/2176/4502/files/Sweater_0.jpg?v=1603266982"],
"price": "74",
"tag": "T-shirt",
"compare_at_price": "200",
"options": [
{
"id": "1010",
"name": "Size",
"value": "US 8"
}, {
"id": "1011",
"name": "Size",
"value": "US 9"
}, {
"id": "1012",
"name": "Size",
"value": "US 10"
}, {
"id": "1013",
"name": "Size",
"value": "US 11"
}, {
"id": "1014",
"name": "Size",
"value": "US 13"
}
]
},
im facing issue to retrieve the data from json file Like i m not able render the data so please help over this
Getting error while mapping the data
im facing issue to retrieve the data from json file Like i m not able render the data so please help over this
useEffect(() =>
{
const fetchData = async () =>
{
const result = await axios.get("https://cdn.shopify.com/s/files/1/0455/2176/4502/files/products.json")
setposts(result.data)
}
fetchData();
}, [])
posts?.map(post => <li>{post.name}</li>)
The issue lies with this file: https://cdn.shopify.com/s/files/1/0455/2176/4502/files/products.json
It returns a an invalid JSON string. So when your axios gets its contents, it sets your posts variable to a simple string, which obviously cannot be mapped through. Hence the error.
The reason axios does not convert it into a JS array is because the file does not contain valid JSON to parse.
The reason the JSON in the file is invalid is because it has a trailing comma after the very last object of the array. See image:
The reason this isn't working for you is, result.data is a string, not an array.
You'll have to convert result.data to array with JSON.parse
Also, the json you're using has a training comma which has to be handled for JSON.parse to work
following code worked for me:
export default function App() {
const [posts, setposts] = useState([]);
useEffect(async () => {
const fetchData = async () => {
const result = await axios.get(
"https://cdn.shopify.com/s/files/1/0455/2176/4502/files/products.json"
);
let regex = /\,(?!\s*?[\{\[\"\'\w])/g;
let correct = result.data.replace(regex, "");
setposts(JSON.parse(correct));
};
fetchData();
}, []);
return (
<div className="App">
{posts.map((post) => (
<li>{post.name}</li>
))}
</div>
);
}

How to fetch array inside another object using Axios?

that's my API, i want to fetch it using axios
[
{
"groupType": "Interessegruppe",
"groups": [
{
"id": "c42b0250-375e-4458-8f68-0df8179f889c",
"name": "Teater",
"assignmentStrategy": 1
},
{
"id": "0fb94732-2bb1-483b-abbd-858327339ca0",
"name": "Fotball",
"assignmentStrategy": 1
},
{
"id": "6b109ab1-5a3e-46b0-b0cc-e2b48d6e2dc6",
"name": "Foto",
"assignmentStrategy": 1
}
]
},
]
I wrote that code
renderItem={({ item }) => <GroupCard title={item.groupType} subTitle={item.groups.name} />}
/>
and I fetched the groupType, but I can't fetch any of [ id or name]
async function loadData() {
const data = await axios.get(url)
return data[0].groups;
}
This function would return the groups array with id and name attributes.

How to Nesting React Components with JSON data

I'm trying to map 4 separate components into their respective rows using JSON data.
You can see the app here - https://stackblitz.com/edit/react-kt1zf8
Data.json
const data = {
"lanes":[
{
"_uid": "001",
"name": "Lane1",
"type": "Toll",
"cars":[
{
"component": "Bmw",
"name": "i8",
"number": "12345",
},
{
"component": "Lambo",
"name": "Aventador",
"number": "214512512",
},
]
},
{
"_uid": "002",
"name": "Lane2",
"type": "Easy Pay",
"cars":[
{
"component": "Fiat",
"name": "i8",
"number": "12345",
},
{
"component": "Dodge",
"name": "Aventador",
"number": "214512512",
},
]
},
]
}
export default data
The Rows are rendered in their own component using the "uid" key from JSON.
Mapping the row data (Lanes & Car Type) is rendering correctly. In the stack blitz, you can see the data in each row is unique.
However, when I try to map the nested data, only the results of the first lane is returning on both rows.
In the Components.jsx, I am using the unique id ("uid") key of the lanes in data.js to determine the lanes but can't figure out what I'm doing wrong. Why are only the first two results showing when they are using the same key?
CarContainer
const CarContainer = (props) => {
return (
<div className="car-container">
{props.data.cars.map(block => Components(block))}
</div>
);
};
export default CarContainer;
LaneInfo
const LaneInfo = () => {
const [laneData, setLaneData] = React.useState(null);
React.useEffect(() => {
setLaneData(data.lanes);
}, []);
return (
<>
{laneData &&
laneData.map((p) => (
<>
<div className="lane">
<div className="space" key={p.uid}>
<div>{p.name}</div>
<div>{p.type}</div>
</div>
</div>
<CarContainer data={p}/>
</>
))}
</>
);
};
export default LaneInfo;

How to use third party extension in react app?

I am implementing razorpay payment in my react app. Below is the code given in the doc.
<button id="rzp-button1">Pay</button>
<script src = "https://checkout.razorpay.com/v1/checkout.js" > < / script>
<script>
var options = {
"key": "YOUR_KEY_ID",
"amount": "2000", // 2000 paise = INR 20
"name": "Merchant Name",
"description": "Purchase Description",
"image": "/your_logo.png",
"handler": function (response) {
alert(response.razorpay_payment_id);
},
"prefill": {
"name": "Harshil Mathur",
"email": "harshil#razorpay.com"
},
"notes": {
"address": "Hello World"
},
"theme": {
"color": "#F37254"
}
};
var rzp1 = new Razorpay(options);
document.getElementById('rzp-button1').onclick = function (e) {
rzp1.open();
e.preventDefault();
}
</script>
So how do I implement it in react. I can put onClick on the button and can call the rzp1.open();. But I think it will through undefined for that. Also the https://checkout.razorpay.com/v1/checkout.js should it be loaded from index.html file? I am very much confused here. Please help me out.
if you want to setup a react component to do this I would recommend you make it extendable and reusable (thats what react components are for!)
class RazorPay extends Component {
constructor(props){
super(props);
this.options = Object.assign(
{},
{
"key": "YOUR_KEY_ID",
"amount": "2000", // 2000 paise = INR 20
"name": "Merchant Name",
"description": "Purchase Description",
"image": "/your_logo.png",
"handler": (response) => {
alert(response.razorpay_payment_id);
},
"prefill": {
"name": "Harshil Mathur",
"email": "harshil#razorpay.com"
},
"notes": {
"address": "Hello World"
},
"theme": {
"color": "#F37254"
}
},
props.rzp1 // any options you pass via props will override the defaults
);
}
componentWillMount(){
this.rzp1 = new window.Razorpay(options);
}
handleClick = (e) =>
this.rzp1.open();
e.preventDefault();
}
render(){
return(
<div>
<button onClick={this.handleClick}>Open</button>
</div>
)
}
}
to use this component and pass a different amount to charge you would just do something like this
const someOptions = {amount: '100'}; // somewhere in the render method.
<RazorPay rzp1={someOptions} /> // somewhere in the return of the render method
recommendations: move most of those default options to a config file that you can import and use. try to abstract as much as you can. it'll make your code easier to use
You can use third party libraries by applying them in componentDidMount() . i.e you can bind library to DOM after it's rendered.
In your case library don't need DOM element but certain options not related to DOM. So you can also initialise it before rendering your component.
An example to your case.
class YourComponentWithButton extends React.Component{
constructor(props){
super(props);
this.state = {
rzp1: null //holds your external library instance
//your initial state if any
}
}
componentDidMount(){ //you can also keep this code in componentWillMount()
var options = {
"key": "YOUR_KEY_ID",
"amount": "2000", // 2000 paise = INR 20
"name": "Merchant Name",
"description": "Purchase Description",
"image": "/your_logo.png",
"handler": function (response) {
alert(response.razorpay_payment_id);
},
"prefill": {
"name": "Harshil Mathur",
"email": "harshil#razorpay.com"
},
"notes": {
"address": "Hello World"
},
"theme": {
"color": "#F37254"
}
};
this.setState({
rzp1 : new window.Razorpay(options)
})
}
buttonClick(event){
if(state.rzp1){ //sanity check whether library loaded to varibale
this.state.rzp1.open();
}
e.preventDefault();
}
render(){
return(
<div className="your-container">
<button onClick={this.buttonClick.bind(this)}>Your Button</button>
</div>
)
}
}

Categories