React & Next js: Only render div if prop contains value - javascript

Im working through my app, but I'm stuck on an issue.
I have some data from contentful which I passed as props to my component. There is one piece of data that I only want to render if it contains any value.
This work to an extent, however, the background still shows.
<div className="text-white font-base text-xs text-center p-1.5 bg-black">
{`${mrr ? mrr : ""}`}
</div>
picture of the frontend
picture of the frontend 2
If anyone could help, that would be great.

#famouslastwords
The TopW3's answer is correct. I will try to explain the code.
The below text will be rendered only when mrr is true. It is same as executing below code:
const result = true && anything; // result = anything
or
const result = false && anything // result = false
{mrr && (
<div className="text-white font-base text-xs text-center p-1.5 bg-black">
{mrr}
</div>
)}

Try this code.
{mrr && (
<div className="text-white font-base text-xs text-center p-1.5 bg-black">
{mrr}
</div>
)}

Related

How to distinguish user clicks between different buttons?

I have rendered 3 plan options from an object array I get from the backend.
If the plan being rendered is
cheaper, the user's subscription then its corresponding button would say downgrade,
costlier, the button would say upgrade, if it is the same then the button would say current.
This logic for rendering is working fine.
But when users click on a button I am not able to identify which option they clicked. I need to update the handle click events based on the plan being rendered.
Currently, I am iterating through the tiers map, and for each tier, I am rendering the button with appropriate text. The function to display the text basically checks for the tiered pricing and returns upgrade or downgrade or current plan. I need a way to update the handle click just like the text.
How can I dynamically update the handle click events based on the tier being rendered?
const [confirmation, setConfirmation] = useState(false);
const handleConfirmation = () => {
setConfirmation(true);
console.log('button is clicked');
};
<div className='px-8 lg:px-24 grid grid-cols-3 gap-8'>
{tiers.map((tier) => (
<div
key={tier.title}
className='relative p-8 bg-white border border-gray-200 rounded-2xl shadow-sm flex flex-col'
>
<div className='flex-1'>
<h3 className='text-xl font-semibold text-gray-900'>{tier.title}</h3>
{tier.value ? (
<p className='absolute top-0 py-1.5 px-4 bg-grays-600 rounded-full text-xs font-semibold uppercase tracking-wide text-white transform-translate-y-1/2'>
VALUE PLAN
</p>
) : tier.recommended ? (
<p className='absolute top-0 py-1.5 px-4 bg-blue-500 rounded-full text-xs font-semibold uppercase tracking-wide text-white transform -translate-y-1/2'>
RECOMMENDED PLAN
</p>
) : (
''
)}
<Button
text={determineCTAText(tier)}
size='fullwidth'
variant='primary'
className='m-auto mt-8 text-center block'
handleClick={handleConfirmation}>
</Button>
}
You can modify the handleConfirmation function to receive a tier object and return a function instead. This will create a closure over the tier value and let you access it when the button's callback is called.
const handleConfirmation = (tier) => {
// Returns the callback function that will be called, with the specific `tier` value in scope
return () => {
setConfirmation(true);
// You can access any `tier` property here
console.log(`button for tier ${tier.title} was clicked`);
};
}
return (
<div className='px-8 lg:px-24 grid grid-cols-3 gap-8'>
{tiers.map((tier) => (
{/* Omitted rest of the JSX for simplicity */}
<Button
text={determineCTAText(tier)}
size='fullwidth'
variant='primary'
className='m-auto mt-8 text-centerblock'
handleClick={handleConfirmation(tier)}>
</Button>
}
</div>
)

How to get parent div in handleChange with React

I have multiple divs that are dynamic (it depends on which filter the visitor checked). So I can not use getElementById.
I need to get the parent div to change its CSS if an input is checked.
Here is my code:
{workout?.map(x => {
return <div className='relative bg-gray-200 p-4 rounded-md my-3 mx-2' key={x.name}>
<input onClick={handleChecked} className='absolute right-0 top-0' type="checkbox" />
<div className='flex'>
<img className='w-2/6 rounded mr-5' src={`${x.path}`} alt={x.name} />
<div className='w-4/6'>
<h2 className='text-xl'>{x.name}</h2>
<p>Nombre de séries : {x.set}</p>
<p>Nombre de rép : {x.reps}</p>
{x.secondary ? <p>Muscles solicités : <br />
<span className='space-x-2'>
{x?.secondary?.map(k => {
return <span className='bg-white px-1 rounded-md' key={k}>{k}</span>
})}
</span>
</p> : null}
</div>
</div>
</div>
})}
The idea, is to add a border-2 border-teal-500 class to the parent div of the input when it is checked.
Here is my handleChecked:
function handleChecked(e) {
// code here
}
I saw that I had to use parentNode but the problem is, I can't store in a variable the current input because it is dynamic. Every item has its own input.
Any idea how I can handle this?
You shouldn't be using getElementById (or any other vanilla JS DOM method) in React anyway - store and change values in state instead. You can leverage this by making input a controlled component, and storing the checked values in an array, or in workout - then, when returning the JSX, you just need to check whether the x variable (the item being iterated over) indicates that the current input should be checked or not - which will also tell you whether the parent should have a different class.
const makeHandleChecked = (i) => (e) = {
setWorkout(
workout.map(
(w, j) => j !== i ? w : { ...w, checked: e.target.checked }
)
);
};
{workout?.map((x, i) => (
<div className={`relative bg-gray-200 p-4 rounded-md my-3 mx-2${x.checked ? ' checked' : ''}`} key={x.name}>
<input onClick={makeHandleChecked(i)} checked={x.checked} className='absolute right-0 top-0' type="checkbox" />

React js :- Too many re-renders. React limits the number of renders to prevent an infinite loop

Q. i want to setstate of every answer map an arrray.
please hep me out.
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
const CreateQuestion = () => {
const { id } = useParams();
const [quesindex, setQuesIndex] = useState(0);
const [answer, setAnswer] = useState();
const [selected, setSelected] = useState("");
const [error, setError] = useState("");
const authContext = useContext(AuthContext);
const [QuestionData, setQuestionData] = useState([]);
useEffect(
function () {
getTestSeries();
},
[id]
);
const getTestSeries = async () => {
try {
const token = authContext.token;
const response = await Api.get(`/user/getallquestions/${id}`, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
if (response.status === 200) {
setQuestionData(response.data["getAllQuestions"]);
} else {
toast(response.data.message);
}
} catch (error) {
toast(error.message);
}
};
const handleSubmit = () => {};
return (
<>
<h1 className="mx-auto flex justify-center my-3 text-5xl font-bold">
Test Series
</h1>
<div>
{QuestionData.length > 0 &&
QuestionData.map(function (ObjectData, index) {
const {
questiontext,
questionImgURL,
options,
answers,
description,
} = ObjectData;
```
while setAnswer state on every loop
```
setAnswer(answer);
return (
<>
<div key={index} className="my-2 mx-5 md:col-span-2">
<div className="shadow px-10 py-2 bg-purple-100 sm:rounded-md sm:overflow-hidden">
<div className=" w-full space-y-6">
<div className="grid grid-cols-3 gap-6">
<div className="col-span-3 sm:col-span-2">
<h1 className=" flex text-lg font-medium space-x-1 text-gray-700">
<span className="font-semibold text-lg">
{index + 1} .
</span>
{questiontext}
</h1>
</div>
{questionImgURL === "" ? (
<div />
) : (
<div className="col-span-3 sm:col-span-2">
<img
alt="question img"
className="max-w-full object-cover max-h-40 border-2 border-red-500"
src={`https://api.microstudy.org/${questionImgURL}`}
></img>
</div>
)}
</div>
<div className="mt-4 space-y-2">
{options.length > 0 &&
options.map((options, index) => {
const { id, optiontext } = options;
return (
<div
className="flex items-center justify-start "
key={index}
>
<input
id={optiontext}
name="options"
type="radio"
value={id}
onChange={changehandler}
className="focus:ring-purple-500 h-4 w-4 text-purple-600 border-gray-800"
/>
<label
htmlFor={optiontext}
className="ml-3 block text-base font-medium text-gray-900"
>
{optiontext}
</label>
</div>
);
})}
</div>
</div>
</div>
</div>
</>
);
})}
<div className=" text-center my-3">
<button
type="submit"
onClick={handleSubmit}
className="inline-flex justify-center py-2 px-8 border border-transparent shadow-md text-lg font-semibold rounded-md text-gray-900 bg-purple-400 hover:bg-purple-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
>
Submit
</button>
</div>
</div>
</>
);
};
please Ignore below text
Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).Please add some context to explain the code sections (or check that you have not incorrectly formatted all of your question as code).
Explanation
The error lies in the onClick prop of your button. In your current implementation,handleSubmit is being called in every render loop. To fix this, we can wrap the handleSubmit function in an arrow function, ensuring that it will only called if the button is being clicked.
Your code
<button
type="submit"
onClick={handleSubmit}
className="inline-flex justify-center py-2 px-8 border border-transparent shadow-md text-lg font-semibold rounded-md text-gray-900 bg-purple-400 hover:bg-purple-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
>
Fix
<button
type="submit"
onClick={() => handleSubmit}
className="inline-flex justify-center py-2 px-8 border border-transparent shadow-md text-lg font-semibold rounded-md text-gray-900 bg-purple-400 hover:bg-purple-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
>

take out name of dynamically created cards react

I had created some cards from an array of objects, now I want to show popup data for each card differently.
here is my code of printing
{data.carData.map( single=>(<li>{ <div onClick={handleClick}><Card single={single}/></div>} </li>))}
for this, I want the card name onClick event, but when I pass anything in the handleClick react throw an error of too many re-renders.
if I do the same onClick event inside the card component and log it prints all the cards names one by one
here is what is inside the card:
function Card({single}) {
const [flowName, setflowName] = useState();
const handleClick=(e)=>{
setflowName(e);
return
}
console.log("loging name:",flowName);
return (
<div className="main mb-2 z-0" onClick={handleClick(e=>single?.flowName)} >
<div className=" inner_main_container pt-4 px-8 bg-white shadow-lg rounded-lg ">
<div className="flex justify-between">
<div className="flex flex-row align-center">
</div>
{single?.badge.map(badge=>(
<div className={"badge"} key={badge}>
<span className={badge==="Growth"?" badgeClrG":(badge==="Content"?"content":"badgeClrO")} key={badge}>{badge}</span>
</div>
) )}
</div>
<div className="flex justify-center">
<img src={single?.image} alt={single?.flowName} />
</div>
<div >
<div className={"mt-2 flex justify-center"}>
<h1>{single?.flowName}</h1>
</div>
</div>
</div>
</div>
) } export default Card
I suspect you're doing this when you're trying to pass a value:
single=>(<li>{ <div onClick={handleClick(value)}><Card single={single}/></div>} </li>))}
Every time this is rendered, the function is invoked straight away, which causes another render and so on...
The solution is to wrap your handleClick call in another function:
single=>(<li>{ <div onClick={()=>handleClick(value)}><Card single={single}/></div>} </li>))}

2 col layout expanding past max width (TAILWIND CSS)

Here's a quick rundown of the relevant code before I ask this question
The HomePage component
const Home = () => {
return (
<div>
<div>
{questions.map((question) => (
<div key={question.id} className="mb-4">
<Question
title={question.title}
contentPreview={question.contentPreview}
/>
</div>
))}
</div>
<Card className="p-4">Side Controlls</Card>
</div>
);
};
The Question component
const Question = ({ title, contentPreview }) => (
<Card className="p-4 break-words">
<h1 className="mb-4 text-lg text-blue-600">{title}</h1>
<p className="text-gray-500">{contentPreview}</p>
<div className="flex mt-4 gap-4">
<InfoIcon
icon={<HeartIcon />}
info={20}
iconClassName="text-red-400 w-6 h-6"
infoClassName="text-gray-500"
/>
<InfoIcon
icon={<CommentIcon />}
info={40}
iconClassName="text-blue-400 w-6 h-6"
infoClassName="text-gray-500"
/>
</div>
</Card>
);
The Layout component that HomePage is being wrapped in
const Layout = ({ children }) => (
<div className="bg-gray-100">
<div className="flex flex-col min-h-screen">
<NavBar />
<div className="mt-4 max-w-7xl self-center w-full px-4">{children}</div>
</div>
</div>
);
And here are some screenshots of whats happening
A screenshot with the containing div of the HomePage Component having a background so you can see better where it is
https://gyazo.com/b8aa356912f973f854299c665c66de76
A screenshot with the div that containing all the questions colored is the reddish color
and the (soon to be) controls/sidebar colored in green
https://gyazo.com/2ceb6a1277f1de4506531a2bcf0b9b17
And finally, the real problem is this screenshot, because I want both the controls and List of questions to be side by side my first instinct is to give the containing div of both of them a class of "flex" but when I do that this happens
https://gyazo.com/af6206b95dc684bbcb316a8d33362b62
and the controls get push beyond the "limits" to the right. if anyone knows or has any ideas about why this might be happening please let me know. thank you
(PS. please do not answer and say "use bootstrap" or use "x ui framework instead" because I'm using tailwind and do want to stay in tailwind)
I want both the controls and List of questions to be side by side
In such case, use flex flex-1 on both the sections to have even width. Else, you can still specify a width like question section flex w-8/12 and the side controls section flex w-4/12.

Categories

Resources