Is it possible to change button text that is created using array. If it is possible, what should I do with the onClick function in the button. Here is the sample code :
function RenderFeeds(props) {
const list = []
props.products.forEach((product) => {
list.push(
<>
<h1>{product.name}</h1>
<h2>{product.company_name}</h2>
<h2>{product.description}</h2>
<button onClick={}>{product.watchlist==false ? 'Add to watchlist':'Remove From watchlist'}</button>
</>
)
})
return (
<>
{list}
</>
)}
So basically I have an array which contains this value :
[{
"name": "lorem ipsum",
"description": "Nam vel nisi rutrum quam ",
"company_name": "PT dapibus ",
"company_slug": "pt-dapibus",
"watchlist": true,
"id": 1
}]
I am creating the component using this array. The watchlist variable will affect the text in the button. If it is true then I want the button to have Remove From Watchlist and viceversa.
I am aware that we can use hook in React and apply useState for onClick button function. But I do not know how do I initialize the state if I use loop to create the component.
CodePudding user response:
In the below snippet I've implemented an example, just for keep it simple, I've used static data as list. I hope it could help.
const data = [{ "name": "lorem ipsum", "description": "description1", "company_name": "PT dapibus ", "company_slug": "pt-dapibus", "watchlist": true, "id": 1 },{ "name": "lorem ipsum2", "description": "description2", "company_name": "Google", "company_slug": "company_slug", "watchlist": true, "id": 2 }]
function RenderFeeds({ feeds, onAddToWatch, onRemoveFromWatch }) {
return (
<React.Fragment>{/* or any markup you want */}
{feeds.map((feed) => (
<div className="feed" key={feed.id}>
<h1>{feed.name}</h1>
<h2>{feed.company_name}</h2>
<h2>{feed.description}</h2>
<button
onClick={() =>
feed.watchlist
? onRemoveFromWatch(feed.id)
: onAddToWatch(feed.id)
}
>
{feed.watchlist ? 'Remove From watchlist' : 'Add to watchlist'}
</button>
</div>
))}
</React.Fragment>
);
}
function Feed() {
const [feeds, setFeeds] = React.useState([]);
React.useEffect(() => {
//receiving data, for example fetching data by ajax or whatever
setFeeds(data);
}, []);
const handleAddToWatch = (id) => {
// implement updating feeds, for example making an ajax request and getting new data
setFeeds((feeds) =>
feeds.map((feed) => ({
...feed,
watchlist: feed.id == id ? true : feed.watchlist,
}))
);
};
const handleRemoveFromWatch = (id) => {
// implement updating feeds, for example making an ajax request and getting new data
setFeeds(feeds =>
feeds.map((feed) => ({
...feed,
watchlist: feed.id == id ? false : feed.watchlist,
}))
);
};
return (
<RenderFeeds
feeds={feeds}
onAddToWatch={handleAddToWatch}
onRemoveFromWatch={handleRemoveFromWatch}
/>
);
}
ReactDOM.render(<Feed/>, document.getElementById('root'))
.feed{
border: 2px solid #ccc;
padding: 15px;
margin: 15px;
}
.feed h1{ margin: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
CodePudding user response:
If you are rendering stuff based on props, it is not really necessary to use hooks in this case.
Something like this should work:
function RenderFeeds(props) {
return (
<>
{props.products.map((product) => {
return (
<>
<h1>{product.name}</h1>
<h2>{product.company_name}</h2>
<h2>{product.description}</h2>
<button onClick={}>{product.watchlist==false ? 'Add to watchlist':'Remove From watchlist'}</button>
</>
)
})}
</>
)}
CodePudding user response:
There is no need to create one extra variable list
and looping over products list which you're getting as props and then pushing it to list
and then rendering list
instead you can directly loop over products list using map
. And there is no need to check product.watchlist==false
when you can use ! Logical NOT
function RenderFeeds(props) {
return (
<>
{props.products.map((product) => {
return (
<>
<h1>{product.name}</h1>
<h2>{product.company_name}</h2>
<h2>{product.description}</h2>
<button onClick={}>{!product.watchlist ? 'Add to watchlist':'Remove From watchlist'}</button>
</>
)
})}
</>
)}
CodePudding user response:
Firstly I would highly recommend you to use Array.map() method instead of using Array.forEach() to create an array of List components because Array.map() itself return an array with new mappings.
And the thing or concept you are looking for in solving this problem is called conditional rendering
.
You can use the ternary operator
or also known as conditional operators
for the purpose of doing conditional rendering
because JSX expects an expression
that can be evaluated to something.
<button onClick={()=>alert('Watchlist changed')}>{product.watchlist==true? 'Add to watchlist':'Remove From watchlist'}