Currently i'm trying to display some products that are in the Stripe Database. I was trying to do by using if statements, filter and with the new Search API of stripe, but I my mission fail. Some ideia of what could I do?
And Other question, how to I display the feature list of each product?
import Router from "next/router";
export default function Product({ prices, category }) {
return (
<>
<section className="product__container">
{prices.map((price, index) => {
if (price.product.metadata.category === category) {
productCard(price, index);
}
})}
</section>
</>
)}
export function productCard(price, index) {
const amount = price.unit_amount / 100;
return (
<div key={index} onClick={() => Router.push(`/${price.id}`)}>
<img src={price.product.images[0]} alt={price.product.name} />
<p>{price.product.name}</p>
<small>Feature List</small>
<p>€{amount.toFixed(2)}</p>
</div>
);}
I solved the problem like this, if you have better ways I would appreciate it I am open to new possibilities.
import Router from "next/router";
export default function Product({ prices, category }) {
const arr = [];
prices.map((price, index) => {
if (price.product.metadata.category == category && arr) {
arr.push(price);
}
});
return (
<>
<section className="product__container">
{arr.map((price, index) => {
const amount = price.unit_amount / 100;
return (
<div
key={index}
onClick={() => Router.push(`/${price.id}`)}
>
<img
src={price.product.images[0]}
alt={price.product.name}
/>
<p>{price.product.name}</p>
<small>Feature List</small>
<p>€{amount.toFixed(2)}</p>
</div>
);
})}
</section>
</>
);}
Related
I am trying to make a simple react app that pulls info from a MySQL database ("username", "balance", "purchases").
So far, I've used node and react to pull from the database with an HTTP query and to display each element on the website.
I then created the API query for searching the database for all entries that start with what I've typed into the search bar.
The issue I'm running into is how do I change the state of the elements that display the username, etc with the new filtered information from the API query? The search bar and data elements are two separate components so I can't use the use effect hook natively.
I cant use the filter method because the database is huge and I've sent my query limit to 100.
Here's my code so far:
PlayerData.js
import axios from 'axios';
import React,{useState, useEffect} from 'react';
const Player = () => {
const [playerData,setPlayerData]=useState([])
useEffect(()=>{
axios.get("http://localhost:3001/api/get").then((res)=>{
console.log(res.data)
setPlayerData(res.data)
})
.catch(err=>{
console.log(err);
})
},[])
return (
<>
{playerData.map((data,id)=>{
return <div className="Player" key={id}>
<span className="Username"> { data.name } </span>
<span className="Crystals"> { data.balance } </span>
<span className="DateModi"> {Object.keys(JSON.parse(data.items)).length} </span>
</div>
})}
</>
)
};
export default Player;
SearchBar.js
import { useState } from "react";
import axios from 'axios'
const Search = () => {
const [searchTerm, setSearchTerm] = useState("")
axios.get(`http://localhost:3001/api/getSearchName/${searchTerm}`).then((res)=>{
console.log(res.data)
})
return (
<div className="Search">
<input className = "InputField" type="text" placeholder="Enter Username:" onChange={e => {setSearchTerm(e.target.value)}}/>
<span className="SearchButton" onClick={console.log(searchTerm)}>
Search
</span>
</div>
)
};
export default Search;
If I understood the question correctly, you need to set the state of PlayerData to a shared component(App), and pass it to the Player.js component. Then when searching it will be overwritten and update the information in the Player.js
function App() {
const [playerData, setPlayerData] = useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = () =>
axios
.get("http://localhost:3001/api/get")
.then((res) => {
setPlayerData(res.data);
})
.catch((err) => {
console.log(err);
});
const handleSearch = (text) => {
const clearText = text.trim();
if (!clearText.length) {
fetchData();
return;
}
axios
.get(`http://localhost:3001/api/getSearchName/${clearText}`)
.then((res) => {
setPlayerData(res.data);
});
};
return (
<div>
<div>
<Search handleSearch={handleSearch} />
</div>
<div>
<Player playerData={playerData} />
</div>
</div>
);
}
Search.js
const Search = ({ handleSearch }) => {
const [searchTerm, setSearchTerm] = useState("");
return (
<div className="Search">
<input
className="InputField"
type="text"
placeholder="Enter Username:"
onChange={(e) => {
setSearchTerm(e.target.value);
}}
/>
<span className="SearchButton" onClick={() => handleSearch(searchTerm)}>
Search
</span>
</div>
);
};
Player.js
const Player = ({ playerData }) => {
return (
<>
{playerData?.length ? (
playerData.map((data, id) => {
return (
<div className="Player" key={id}>
<span className="Username"> {data.name} </span>
<span className="Crystals"> {data.balance} </span>
<span className="DateModi">
{" "}
{Object.keys(JSON.parse(data.items)).length}{" "}
</span>
</div>
);
})
) : (
<div>Loading...</div>
)}
</>
);
};
I'm new to Reactjs. I'm unable to extract image url from the API. I'm really sorry if similar type of threads already exist in stackoverflow. Full code is below.
The API I used is: https://api.thecatapi.com/v1/breeds
import React, { Component } from "react";
import ReactDOM from "react-dom";
const Cat = ({
cat: {name, image},
}) => {
return(
<div className='catMain'>
<div className='catImage'>
<img src={image.url} alt={name} />
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
};
componentDidMount() {
this.fetchCatData();
}
fetchCatData = async () => {
const url1 = "https://api.thecatapi.com/v1/breeds"
const response = await fetch(url1)
const data = await response.json()
this.setState({
data,
})
}
render() {
return (
<div className='main'>
<div className="cats">
<div className="catsInfo">
{this.state.data.map((cat) => (
<Cat cat={cat}/>
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
If you want to display every cat even though they might not have an image, you can do this:
const Cat = ({ cat: { name, image } }) => {
return (
<div className="catMain">
{image && (
<div className="catImage">
<img src={image.url} alt={name} />
</div>
)}
</div>
);
};
Then you can just display whatever else you want about the cat, without having to worry about image issues.
You have an assumption that every cat has an image, that's not the case, therefore you can filter empty images beforehand (there are tons of solutions, conditional rendering can be done too):
// cat.image is an object, which is truthy value therefore you can filter by it.
this.state.data.filter(cat => cat.image).map(cat => <Cat cat={cat} />)
// OR, conditional rendering
this.state.data.map(cat => cat.image && <Cat cat={cat} />)
// Or in the component itself, etc.
const Cat = ({ cat: { name, image } }) => {
return image ? (
<div className="catMain">
<div className="catImage">
<img src={image.url} alt={name} />
</div>
</div>
) : (
<Placeholder />
);
};
I have multiple variants in my one component, and I want that if I click on any variant it should add active class to it and removes active class from another. But I am stuck how it can happen using state in multiple variants loop.
Here is my code:
import { useState } from "react";
const Variants = () => {
// Sample Variants Object - But in real it's coming from Wordpress back-end GraphQL
const vats = {
"Tech": ['3G', '5G'],
"Color": ['Red', 'Gray']
}
const [selectedTech, techToChange] = useState(null);
return (
<div>
{vats && (
<div>
{Object.keys(vats).map((key, value) => (
<div key={key}>
<div><b>{key}</b></div>
{vats[key].map((val) => (
<div key={val} onClick={() => techToChange('active')}>
<label
className="cursor-pointer bg-yellow-100"
>
{val} - {selectedTech}
</label>
</div>
))}
<hr/>
</div>
))}
</div>
)}
<hr />
</div>
)
}
You can see in my code, there are 2 variants named Tech & Color, For example; If I click on 3G of tech, it should add active class to it and removes active class from 5G & If I click on Red it should add active class to it and removes active class from Gray. Can someone please help me to do it? I am stuck
You're just setting selectedTech to 'active'–this is just a string and doesn't create any sort of relationship between the tech clicked and the selectedTech in state.
To fix this, you need to set the selectedTech to the actual val of the one you clicked. To add the variant separation you want, the state can mimic the shape of your variants and be an object. So instead of setting selectedTech directly, you can set selectedTech[variant] to the value you clicked.
And then, with a little evaluation, you can print out the string, active when you click on one.
import { useState } from "react";
export default () => {
// Sample Variants Object - But in real it's coming from Wordpress back-end GraphQL
const vats = {
Tech: ["3G", "5G"],
Color: ["Red", "Gray"]
};
const initialState = Object.fromEntries(Object.keys(vats).map((key)=> [key, null])); const [selectedTech, techToChange] = useState(initialState);
return (
<div>
{vats && (
<div>
{Object.keys(vats).map((key, value) => (
<div key={key}>
<div>
<b>{key}</b>
</div>
{vats[key].map((val) => (
<div key={val} onClick={() => techToChange((c) => ({...c, [key]: val}))}>
<label className="cursor-pointer bg-yellow-100">
{val} - {selectedTech[key] === val ? "active" : null}
</label>
</div>
))}
<hr />
</div>
))}
</div>
)}
<hr />
</div>
);
};
CodeSandbox: https://codesandbox.io/s/inspiring-kare-hsphp?file=/src/App.js
useMap from react-use would fit nicely in to your existing code:
const [vats, {set, setAll, remove, reset}] = useMap({
"Tech": ['3G', '5G'],
"Color": ['Red', 'Gray']
}
...
{Object.keys(vats).map((key, value) => (
...
<div key={val} onClick={() => set(key, val)}>
Here is the return code. You need to pass the val to set the state of selectedTech state variable and then compare the actual value with it to have the active class set.
const [selectedTech, techToChange] = useState([]);
const selectOps = (key,val) => {
let existing = selectedTech;
let idx = existing.findIndex(i => i.key===key);
console.log(idx);
if(idx > -1){
existing.splice(idx,1);
console.log(idx, existing);
}
techToChange([...existing, {key,val}]);
}
return (
<div>
{vats && (
<div>
{Object.keys(vats).map((key, value) => (
<div key={key}>
<div><b>{key}</b></div>
{vats[key].map((val) => (
<div key={val} onClick={() => selectOps(key,val)}>
<label
className={`cursor-pointer bg-yellow-100 ${selectedTech.some(s => s.val===val) ? 'active' : undefined}`}
>
{val}
</label>
</div>
))}
<hr/>
</div>
))}
</div>
)}
<hr />
</div>
)
This is an example of using useRef and some other stuff that you might find useful:
import React, { useState, useRef, useEffect} from "react";
const Variants = () => {
// Sample Variants Object - But in real it's coming from Wordpress back-
end GraphQL
const vats = {
"Tech": ['3G', '5G'],
"Color": ['Red', 'Gray']
}
const labelRef = useRef();
const [selectedTech, techToChange] = useState("");
const [selectedColor, colorToChange] = useState("");
useEffect(()=>{
console.log(selectedColor);
if(labelRef.current.innerHTML.trim() === selectedColor) {
labelRef.current.className ="other class";
}
else {
labelRef.current.className ="cursor-pointer bg-yellow-100";
}
},
[selectedColor, labelRef])
useEffect(()=>{
console.log(selectedTech);
if(labelRef.current.innerHTML.trim() === selectedTech) {
labelRef.current.className ="other class";
}
else {
labelRef.current.className ="cursor-pointer bg-yellow-100";
}
},
[selectedTech, labelRef])
return (
<div>
{vats && (
<div>
{Object.keys(vats).map((key, value) => (
<div key={key}>
<div><b>{key}</b></div>
{vats[key].map((val) => (
<div key={val} onClick={(e) => {
if(key==="Tech") {
//console.log(e.target.innerHTML);
techToChange(e.target.innerHTML.trim());
labelRef.current = e.target;
//console.log(val.trim(),selectedTech.trim());
}
else if(key==="Color")
{
colorToChange(e.target.innerHTML.trim())
labelRef.current = e.target;
}
}
}>
<label ref={labelRef}
className="cursor-pointer bg-yellow-100"
>{val}
</label>
</div>
))}
<hr/>
</div>
))}
</div>
)}
<hr />
</div>
)
}
export default Variants;
so the problem is I have a search functionality everything works, except that when an item has not been found, you see it should display the text "champion has not been found" but it is not. I would appreciate the help Where am I making a mistake?
import data from './data.json'
import './Champions.css'
import Skills from './Skills'
import CloseIcon from '#material-ui/icons/Close';
const Champions = ({searchValue}) => {
const [toggleShow, setToggleShow] = useState(false);
const [currentSelectedChampion, setCurrentSelectedChampion] = useState({});
const handleSelectChampion = (id) => {
if (!toggleShow) setToggleShow(true);
const currentChampion = data.filter((champ) => champ.id === id)[0];
setCurrentSelectedChampion(currentChampion);
};
function filterChampions(champion) {
return champion.name.toLowerCase().includes(searchValue.toLowerCase());
}
{data.filter(filterChampions).length === 0 && (<div className='not__found'>
<h1>No champion has been found</h1>
</div>)}
return (
<div className="champions">
{data.filter(filterChampions).map((champion) => {
return (
<div key={champion.id} onClick={() => handleSelectChampion(champion.id) } >
<div className="champion">
<img className="champion__Image" src={champion.image}></img>
<h4 className="champion__Name">{champion.name}</h4>
{toggleShow && currentSelectedChampion.id === champion.id && (
<>
<Skills currentChampion={currentSelectedChampion} />
<CloseIcon onClick={() => setToggleShow(false)}/>
</>
)}
</div>
</div>
);
})}
</div>
);
};
export default Champions
The map in line {data.filter(filterChampions).map((champion) => { will not return anything for empty array.
Consider the following examples.
[].map(e => 'called'); // []
[3].map(e => 'called'); // ['called']
So if {data.filter(filterChampions) returns an empty array the map will return empty array and not the div with class not__found.
What you need to do is something as following
const showChamtions = () => {
// Put the filtered data in a variable
const selectedChampions = champions.filter((element) => element.score > 12);
// If data is there do what you intend to do with it else not_found div
if (selectedChampions && selectedChampions.length > 0) {
return selectedChampions.map((element) => <p>{element.name}</p>);
} else {
return (
<div className="not__found">
<h1>No champion has been found</h1>
</div>
);
}
};
Example - https://codesandbox.io/s/map-on-empty-array-i6m1l?file=/src/App.js:349-741
You can modify your code similar to this using a conditional operator as well.
{data.filter(filterChampions).map((champion) => {
if(data.filter || champion){
return (
<div className='not__found'>
<h1>No champion has been found</h1>
</div>
)
}
This if statement is not nesserasy, if an item has not been found => data.filter(filterChampions) will be an empty array, the map function will return nothing, the if statement doesn't even run.
It you want to display the message, you could simply use this:
{data.filter(filterChampions).length === 0 && (<div className='not__found'>
<h1>No champion has been found</h1>
</div>)}
I have a functional element in react js like this,
function FilterOptions() {
const [isShown, setIsShown] = useState(false);
return (
<div className="filter__options">
{["Category", "Design", "Size", "Style"].map((ourOption) => (
<div
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
className="filter__options__container"
>
<div className="filter__options__button">
{ourOption}
</div>
{isShown && <div className="filter__options__content"> Here I want to return the element using props </div>}
</div>
))}
</div>
);
}
I have created a files called, Category.js, Design.js, Size.js, Style.js.
Now I want to use the props so that I can concatenate like this <{ourOption}> <{ourOption}/> so that this will return element.
Any idea how to do this guys?
Choosing the Type at Runtime
First: Import the components used and create a lookup object
import Category from 'Category';
import Design from 'Design';
import Size from 'Size';
import Style from 'Style';
// ... other imports
const components = {
Category,
Design,
Size,
Style,
// ... other mappings
};
Second: Lookup the component to be rendered
function FilterOptions() {
const [isShown, setIsShown] = useState(false);
return (
<div className="filter__options">
{["Category", "Design", "Size", "Style"].map((ourOption) => {
const Component = components[ourOption];
return (
...
<div className="filter__options__button">
<Component />
</div>
...
))}}
</div>
);
}
Alternatively you can just import and specify them directly in the array to be mapped.
function FilterOptions() {
const [isShown, setIsShown] = useState(false);
return (
<div className="filter__options">
{[Category, Design, Size, Style].map((Component) => (
...
<div className="filter__options__button">
<Component />
</div>
...
))}
</div>
);
}
Instead of strings you could iterate over Array of Components
{[Category, Design, Size, Style].map((Component) => (
<Component/>
);
Ill do this as react document
//create components array
const components = {
photo: Category,
video: Design
.....
};
{
Object.keys(components).map((compName) => {
const SpecificSection = components[compName];
return <SpecificSection />;
})
}
Here is a small sample code that you can work with. Use direct component instead of trying to determine by strings.
const Comp1 = () => {
return <p>Comp1 Here</p>
}
const Comp2 = () => {
return <p>Comp 2 Here</p>
}
export default function App() {
return (
<div className="App">
{[Comp1, Comp2].map(Komponent => {
// use Komponent to prevent overriding Component
return <Komponent></Komponent>
})}
</div>
);
}