How do I pass props when the prop object is created? - javascript

I have a problem wherein I want to pass my props in my prop object as you see in this code
const list = [
{option:'Main',main:<Main></Main>},
{option:'Topic',
main:<Topic
uid={uid}
tindex={topicindex}
setTindex={settopicIndex}
topiclist ={topiclist}
handlePrev = {e => handlePrev(e)}
handleNext = {e => handleNext(e)}
topic={topic}
setTopic={setTopic}
handleAddComment = {e => handleAddComment(e)}
comments = { comments }
comment={comment}
setcomment={setcomment}
handleLikes = {(e) => handleLikes(e,uid,"I'll pass a item")}
handleDislikes = { (e) => handleDislikes(e,uid,"I'll pass a item")}
reacts = {reacts}
setreacts = {setreacts}
></Topic>
},
{option:'Arts',
main:<Arts
uid={uid}
postart={postart}
setpostart={e => setpostart(e)}
delart={delart}
setdelart={e => setdelart(e)}
/>
}]
This list will show in my output function but as you see my main objects will is not changeable in a loop when I try to pass my new items Examples this
handleLikes and handleDislikes, this one as you see I'll pass a item I want to pass a new item there but the item there will be constant. I'll try to explain this briefly in my full codes.
First lets start with <Topic>
const Topic = props => {
<div className="list">
{props.comments.map((item,idx) => {
return(
<div className='user'>
<div className="user-uid">
<h6> {item.uid}</h6>
</div>
<div className="user-comment">
<h5>
{item.comment}
</h5>
</div>
<div className="like-dislike">
<div className="like" onClick={(e,i) => props.handleLikes(item.uid,props.uid,item.likes)}>
{item.likes} <ion-icon name="thumbs-up-outline"></ion-icon>
</div>
<div className="dislike" onClick={(e,i) => props.handleDislikes(item.uid,props.uid,item.dislikes)} >
{item.dislikes} <ion-icon name="thumbs-down-outline"></ion-icon>
</div>
</div>
</div>
)
})}
</div>
}
This one is my call props object( I don't know what it calls to be honest.)
And this one will be my callback
const list = [
{option:'Main',main:<Main></Main>},
{option:'Topic',
main:<Topic
uid={uid}
tindex={topicindex}
setTindex={settopicIndex}
topiclist ={topiclist}
handlePrev = {e => handlePrev(e)}
handleNext = {e => handleNext(e)}
topic={topic}
setTopic={setTopic}
handleAddComment = {e => handleAddComment(e)}
comments = { comments }
comment={comment}
setcomment={setcomment}
handleLikes = {(e,i) => handleLikes(e,uid,i)}
handleDislikes = { (e,i) => handleDislikes(e,uid,i)}
reacts = {reacts}
setreacts = {setreacts}
></Topic>
},
{option:'Arts',
main:<Arts
uid={uid}
postart={postart}
setpostart={e => setpostart(e)}
delart={delart}
setdelart={e => setdelart(e)}
/>
}]
and then I will show this in my output function like this
<div className="main-body">
<div className="slideshow">
<div
className="slideshowSlider"
style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
>
{list.map((item,idx) => {
return(
<div className='slide' key={idx}>
{item.main}
</div>
)
})}
</div>
</div>
</div>
I tried to remove the Topic props in its list and do something like this
const list = [
{option:'Main',main:<Main></Main>},
{option:'Topic',
main:<Topic
></Topic>
},
{option:'Arts',
main:<Arts
uid={uid}
postart={postart}
setpostart={e => setpostart(e)}
delart={delart}
setdelart={e => setdelart(e)}
/>
}]
And for output function
<div className="main-body">
<div className="slideshow">
<div
className="slideshowSlider"
style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
>
{list.map((item,idx) => {
return(
<div className='slide' key={idx}>
{item.main.props ???}
// I want to pass the props here instead of doing it in
the list
</div>
)
})}
</div>
</div>
</div>
Why Am i doing this?
Here's why as you see in the handleLikes and handleDislikes there is a
<div className="like-dislike">
<div className="like" onClick={(e,i) => props.handleLikes(item.uid,props.uid,item.likes)}>
{item.likes} <ion-icon name="thumbs-up-outline"></ion-icon>
</div>
<div className="dislike" onClick={(e,i) => props.handleDislikes(item.uid,props.uid,item.dislikes)} >
{item.dislikes} <ion-icon name="thumbs-down-outline"></ion-icon>
</div>
</div>
I want to pass my item.likes and item.dislikes but the it cannot be pass on my <Topic> at list
Also this is just the code for handleLikes and handleDislikes
const handleLikes = (
main_uid,
reactor_uid,
likes
// likes_state
) => {
console.log('like')
console.log(main_uid,reactor_uid)
console.log(reacts)
console.log(likes)
}
const handleDislikes = (
main_uid,
reactor_uid,
dislikes
) => {
console.log('dislike')
console.log(main_uid,reactor_uid)
console.log(reacts)
console.log(dislikes)
}
but when I tried to console.log it the dislikes or likes just giving me the same input as the item.uid in the Topic props. So I want to do it in this way as item.main.props in part of output function.
I hope my question is clear thank you for helping me.

Related

js react converting dropdown to checkbox filter

Hej!
I am a newbie to javascript but was able to implement a dropdown menu filtering my json-data (everything works fine) but when I convert/change it into checkboxes I won't get any results in my result list.
// dropdown
const ContentBuilder = () => {
const options = [
{ label: "Landwirtschaft", value: "Landwirtschaft" },
{ label: "Forstwirtschaft", value: "Forstwirtschaft" },
]
const [newData, setNewData] = React.useState([]);
const [selectedValue, setSelectedValue] = React.useState(options[0]);
const filteredData = data.filter(x =>
x.Sektor == selectedValue)
const handleFilterInput = (event) => {
let value = event.target.value;
setSelectedValue(value);
};
return (
<section className="content">
<div className="container">
<div className="columns table">
<div className="column is-four-fifth filter">
<label>Sektion <br/>
<select
value={selectedValue}
onChange={handleFilterInput}
>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</label>
</div>
<div className="column is-one-fifth">
<div className="container">
<div className="liste">
<List data={filteredData}/>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
if I only change the select to input and add the 'checkbox' type all I get is an empty page
// checkboxes
.
.
.
<input
type = "checkbox"
className = "sektor-checkbox"
value={selectedValue}
onChange={handleFilterInput}
>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</input>
.
.
.
If I put the 'checkbox' inside the map I get the checkboxes but no result list and therefor no filter.
.
.
.
{options.map((option) => (
<>
<input
type = "checkbox"
className = "sektor-checkbox"
value={selectedValue}
onChange={handleFilterInput}
>
</input>
<option value={option.value}>{option.label}</option>
</>
))}
.
.
.
// json
[
{
"Pflanzenname": ["Hanf (Samen-/Faser-)"],
"Sektor": "Landwirtschaft",
},{
"Pflanzenname": "Soja",
"Sektor": "Landwirtschaft",
},{
"Pflanzenname": "Hirse (Sorghum-/Zucker-)",
"Sektor": "Landwirtschaft",
},{
"Pflanzenname": "Riesenweizengras",
"Sektor": "Forstwirtschaft",
}
]
working dropdown menu:
https://codesandbox.io/s/shy-bash-bj5f5s?file=/src/contentBuilder.js
not working checkboxes:
https://codesandbox.io/s/vigilant-sun-mh3rg9?file=/src/App.js
Does anybody know what I'm missing?
Any help is appreciated! :)
I hope this solution will be work for you , check this live example
Sandox
Use filter logic like this
const filteredData = data.filter(
(x) => x.Sektor === checked.find((item) => item === x.Sektor)
);
Read this doc GoodPractice
use checkbox list like this
<div className="checkList">
<div className="title">Your CheckList:</div>
<div className="list-container">
{options.map((item, index) => (
<div key={index}>
<input onChange={handleCheck} value={item.value} type="checkbox" />
<span>{item.value}</span>
</div>
))}
</div>
</div>
in the change handler write like this
const handleCheck = (event) => {
var updatedList = [...checked];
if (event.target.checked) {
updatedList = [...checked, event.target.value];
} else {
updatedList.splice(checked.indexOf(event.target.value), 1);
}
setChecked(updatedList);
};
Live example Sandbox

how to map image array with filter in ReactJS

I'm absolutely beginner in ReactJS and I want to filter and map
const Shop = [
{
img : jam,
category: 'jam'
},
{
img : headset,
category:'headset'
},
{
img : sepatu,
category:'sepatu'
}
];
let ShopItem = [
{
id : 1,
img : jam,
category : 'jam',
price : 'Rp. 900,000'
},
{
id : 2,
img : jam,
category : 'jam',
price : 'Rp. 900,000'
},
{
id : 3,
img : headset,
category : 'headset',
price : 'Rp. 900,000'
}
]
function Content(){
const [shopItems,toogleshopItems]=useState(false);
let [items,showItems]=useState('');
const toogleShop = ()=>{
toogleshopItems(!shopItems);
console.log(shopItems);
}
function showshopItems(){
return(
<>
{Shopitem.map((shopitem, shopitemIndex) => {
return Shop.map((shop, shopIndex) => {
if (shop.category == shopitem.category)
return <img className="image-place" src={shopitem.img} />;
});
})}
</>
)
}
return(
<>
<div className="content">
<div className="content-wrapper">
<div className="content-title">Browse Categories</div>
<div className="image-flex">
{
Shop.map((shops)=>
<React.Fragment key={shops.category}>
<img onClick={toogleShop} className="image-place" src={shops.img}/>
</React.Fragment>
)}
</div>
<hr/>
{shopItems? showshopItems() : console.log("no") }
</div>
</div>
</>
)
}
export default Content
how to map shopitem image that has the same category value with shop category value...
when I click picture watch
if I click the picture 1 it will show child picture that has category jam
Finally I found out whats your problem. You should have a state for getting current category when user clicks on the top image and filter the items based on the state. I've created a sample based on your request:
export default function App() {
const [currentCategory, setCategory] = useState();
const TopSlide = () => {
return (
<div className="topSlide">
{Shop.map((shop, index) => {
return (
<img
alt=""
className="topSlideImage"
src={shop.img}
onClick={() => {
setCategory(shop.category);
}}
/>
);
})}
</div>
);
};
const DownSlide = () => {
return (
<div className="downSlide">
{ShopItem.filter((x) => x.category === currentCategory).map(
(shop, index) => {
return <img alt="" className="downSlideImage" src={shop.img} />;
}
)}
</div>
);
};
return (
<div className="App">
{TopSlide()}
<hr />
{DownSlide()}
</div>
);
}

Why I have got an empty object from my context?

I have a context and try to pass it to my children components:
const PatientContext = createContext([{}]);
function App() {
const [selectedPatient, setSelectedPatient] = useState([]);
const [patients, setPatients] = useState([{ name: 'Taras', age: 19 }, { name: 'Taras', age: 19 }, { name: 'Taras', age: 19 }]);
async function patientsHasChanged() {
const patientService = new PatientService();
const loadedPatients = await patientService.getPatients();
setPatients(loadedPatients);
};
return (
<div className='app'>
<PatientContext.Provider value={[selectedPatient, setSelectedPatient, patients, patientsHasChanged]}>
<Sidebar />
<Content />
</PatientContext.Provider>
</div>
);
}
But if I try use it in my child components I am always getting empty object, how i can fix it?
img with my problem here
UPD:
Here's my component with using context:
const Sidebar = (props) => {
const [patients, selectedPatient, setSelectedPatient] = useContext(PatientContext);
return (
<div className='sidebar'>
<div className='search'>
<input type="text" placeholder='Search' />
<button>New patient</button>
</div>
<div className='list'>
<ul>
{patients.map((p) =>
<li onClick={setSelectedPatient}>
<div className='name'>
{p.name}
</div>
<div className='age'>
{p.age}
</div>
</li>)
}
</ul>
</div>
</div>
);
};
Your problem is you're using an array ([]) for the context; arrays have a given order. You pass in [selectedPatient, setSelectedPatient, patients, patientsHasChanged], and you're unpacking things in a different order ([patients, selectedPatient, setSelectedPatient]), so you get the "wrong" objects.
Instead, use an object ({}) so you can unpack it as you like, and remember to memoize the context value to avoid unnecessary rerenders.
const PatientContext = React.createContext(null);
const Sidebar = (props) => {
const { patients, selectedPatient, setSelectedPatient } = React.useContext(PatientContext);
return (
<div className="sidebar">
<div className="search">
<input type="text" placeholder="Search" />
<a href="/TechTask/new">
<button>New patient</button>
</a>
</div>
<div className="list">
<ul>
{patients.map((p) => (
<li onClick={setSelectedPatient}>
<div className="name">{p.name}</div>
<div className="age">{p.age}</div>
</li>
))}
</ul>
</div>
</div>
);
};
function App() {
const [selectedPatient, setSelectedPatient] = React.useState([]);
const [patients, setPatients] = React.useState([
{ name: "Taras", age: 19 },
{ name: "Taras", age: 19 },
{ name: "Taras", age: 19 },
]);
function patientsHasChanged() {/* elided since SO doesn't support async */}
const patientContext = React.useMemo(() => ({ selectedPatient, setSelectedPatient, patients, patientsHasChanged }), [
selectedPatient,
setSelectedPatient,
patients,
patientsHasChanged,
]);
return (
<div className="app">
<PatientContext.Provider value={patientContext}>
<Sidebar />
</PatientContext.Provider>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Dynamically sorting an array of objects in a dropdown list

A drop-down list is implemented in which the active class is added when an item in the items array is selected. Everything works, but you need to display the selected item first in the list, and not in any order. I tried this approach const newItems = [selectedAccount, ... items] and then map newItems, but the problem is that then the selected item is displayed twice in the drop-down list.
type TAccountListProps= {
isVisible: boolean;
items: Accounts.Account[];
selectedAccount: Accounts.Account | null;
onSelect: (id: string) => void;
onToggle: (value: boolean) => void;
};
export const AccountList: React.FunctionComponent<TAccountListProps> = ({
isVisible,
items,
selectedAccount,
onSelect,
onToggle
}) => {
if (!isVisible) {
return null;
}
return (
<div className="account-list">
{items.map((item) => {
const isSelected = item.id == selectedAccount?.id;
return (
<div
key={item.id}
className={classnames(
'account-list__account',
{ 'account-list__account_active': isSelected }
)}
onClick={() => {
onSelect(item.id);
onToggle(false);
}}
>
<div className="account-list__icon-block">
<CardOutline className="account-list__icon" />
<div className="account-list__info">
<div className="account-list__name">
Расчётный счёт
</div>
<div className="account-list__number">
{formatAccountNumber(item.num.value)}
</div>
</div>
</div>
{item.balance && (
<div className="account-list__balance">
<span>{item.balance}</span>
<span className="account-list__currency">
{CurrencySigns.Rub}
</span>
</div>
)}
</div>
);
})}
</div>
);
};
So filter out the selected item:
const newItems = [
selectedAccount,
...items.filter(item.id != selectedAccount?.id)
];

TypeError: null spread operator is not iterable

just can't seem to fix this null spread operator which is occurring when my charities (deconstructed from props) is empty. How do I best allow for this case? Any advice would be great. The error is occurring in the onCompleted function.
const Causes = ({ causes, charities }) => {
const [charitiesList, setCharitiesList] = useState(charities);
const causeIds = _.map(causes.edges, i => i.node.databaseId);
var causeYoutubeIds
const { data, loading, error } = useQuery(GET_CHARITIES_BY_CAUSE, {
variables: {
"id": causeIds
},
onCompleted(dt) {
const getCharitiesByCause = _.map(dt.charities.edges, i => ({ charity: i.node }));
setCharitiesList([...charitiesList , ...getCharitiesByCause]);
}
})
return (
<div>
<div className="columns is-multiline">
<div className="column">
<h2 className={styles.heading}>Charities Involved</h2>
<div className={styles.causeContainer}>
{
charitiesList &&
charitiesList.map((item) => {
return (
<div className={styles.charityCard}>
<Img src={item.charity.Charity.logo.mediaItemUrl} />
{item.charity.title}
</div>
)
})
}
</div>
</div>
</div>
</div>
)
}
From what it seems like. useState(charities); This charities is coming null. If it should have a value then you need to fix it. Or you can just add a check. useState(charities || []);

Categories