Template does'nt work with Tailwind in React - javascript

If I put the color directly in the tailwind class like "bg-cianTheme" it works. But if i use javascript template like "bg-${primaryColorTheme}" with the code above doesn't work. Why does it happen and how fix ?
The code:
import { BsGithub, BsLinkedin } from 'react-icons/bs'
export interface INewProfileCardProps {
photo: string
github: string
linkedin: string
colors: string[]
primaryColorTheme: string // tailwind refence collor
secondaryColorTheme: String //tailwind reference collor
terciaryColorTheme: string //tailwind reference collor
labelName: string
}
export function NewProfileCard({
photo,
github,
linkedin,
colors,
labelName,
}: INewProfileCardProps) {
const [primaryColorTheme, secondaryColorTheme, terciaryColorTheme] = colors
console.log(`bg-${primaryColorTheme}`)
return (
<div className="flex items-center justify-center">
<div>{/* <p className="text-[250px]">{'<'}</p> */}</div>
<div className=" relative h-[202px] w-[404px] rounded-xl bg-whiteIcon px-4 py-8 pt-2">
<div
className={`bg-${primaryColorTheme} relative flex h-full w-full`}
>
<img
className="absolute bottom-0"
src={photo}
alt="personal-photo"
></img>
</div>
<div className="absolute flex">
<div
className={`flex items-center justify-center font-bold text-${primaryColorTheme} bg-${primaryColorTheme} rounded-l-xl px-6 py-2`}
>
<BsGithub className="text-2xl" />
<p className="ml-3 text-lg">Git Hub</p>
</div>
<div
className={` bg-${secondaryColorTheme} ${primaryColorTheme} flex items-center justify-center rounded-r-xl px-6 py-2 font-bold`}
>
<BsLinkedin className="text-2xl" />
<p className="ml-3 text-lg">Linkedin</p>
</div>
</div>
</div>
<div>
{/* <p className="text-[250px]">
<span className={`text-${primaryColorTheme}`}>/</span>
{'>'}
</p> */}
</div>
</div>
)
}
I try to change the colors with variables in tailwind class with template, but doesn't work.

The problem is the postcss can't find that class when you have interpolated strings like that. You can add this to tailwind.config.js
safelist: ["bg-somecolor"]
or you can find a way to not use interpolation

In addition to pguardiano's answer, you may be able to achieve the same thing by calling the style attribute directly since postCSS only renders what is readily available in the template...
In your case, you can send the hex code directly to the variable and pass it to the style attribute. Example:
<div
className="relative flex h-full w-full"
style="{{ background: primaryColorThemeColor }}"
>
<img
className="absolute bottom-0"
src={photo}
alt="personal-photo"
/>
</div>
If you want to get your hands dirty and do things in a more interesting way, you can take advantage of Tailwind's theming functionality.
It is explained well in this video: https://www.youtube.com/watch?v=MAtaT8BZEAo.
Then you can update your CSS variables with whatever color is coming from your API I guess. Goodluck hacking your way in :)
Ref:
Updating CSS Variables with Javascript: https://css-tricks.com/updating-a-css-variable-with-javascript/

Related

How to map an array inside JSON object using typescript?

I'm trying to get an array from a JSON object and then, map it in order to get the data.
Here is the data returned from an API:
{
project: [
{
_createdAt: '2022-12-15T16:45:57Z',
_id: 'cb39338d-4e6d-4c28-9a79-499afca392e6',
_rev: '974wCYB6EQ3xW9LGNZhQvU',
_type: 'project',
_updatedAt: '2022-12-27T04:55:54Z',
image: [Object],
linkToBuild: 'https://github.com/Arotiana137-51/charitty_to_portfolio_jsp',
summary: "This is a project I've done for learning purpose at the University. I've learned the basics of web programing with Java Server Pages ,Servelet ,....", technologies: [Array],
title: 'Charity '
}
]
}
And I wish to map this array in order to get elements from it inside this JSX element :
import React from "react";
import {motion} from 'framer-motion';
import { Project } from "../typing";
import { urlFor } from "../sanity";
type Props = {
projects:Project[];
};
function Projects({projects}: Props) {
console.log(projects);
return (
<motion.div
initial={{opacity:0}}
whileInView={{opacity:1}}
transition={{duration:1.5}}
className="h-screen relative flex overflow-hidden flex-col text-left md:flex-row max-w-full justify-evenly mx-auto items-center z-0">
<h3 className="absolute top-24 uppercase tracking-widest text-teal-400 text-2xl ">
Projects
</h3>
<div className="relative w-full flex overflow-x-scroll overflow-y-hidden snap-x snap-mandatory z-20">
{/*----------- HERE I TRY TO ACCESS THE ARRAY AND MAP IT DIRECTLY, LIKE IN JS-----------------------------------*/}
{ projects.project.map((project,i) => (
<div className="w-screen flex-shrink-0 snap-center flex flex-col space-y-5 items-center justify-center p-20 md:p-44 h-screen">
<motion.img
initial ={{
y: -300,
opacity:0
}}
transition={{duration: 1.2}}
whileInView = {{opacity:1 , y:0 }}
viewport={{ once: true}}
src={urlFor(project.image).url()}
alt="#"/>
<div className=" space-y-10 px-0 md:px-10 max-w-6xl ">
<h4 className="text-4xl font-semibold text-center">
Case study {i+1} of{projects.length}: <span className="underline decoration-teal-700"> {project?.title}</span>
</h4>
<div className="flex items-center space-x-2 justify-center">
{
project?.technologies.map((technology)=>(
<img
className="h-10 w-10"
key={technology._id}
src={urlFor(technology?.image).url()}
alt=""
/>
))
}
</div>
<p>{project?.summary}</p>
</div>
</div>
))}
</div>
<div className="w-full absolute top-[30%] bg-teal-800 left-0 h-[500px] -skew-y-12">
</div>
</motion.div>
);
}
export default Projects;
This normally works on js but my compiler return:
Server Error
TypeError: Cannot read properties of undefined (reading 'map')
because it still considers the prop as an object, even if I try to access the array at the code above, how can i solve it?
You are trying to do project?.technologies.map, but as i see at the JSON above , there is simply no "technologies" key.

Incorrect component display when passing props and using Tailwind

I pass the color data to the created component to set a specific color in several places. At the output, it turns out that it is installed only in one place. What could it be? In the project I use only tailwind.
<div className="w-full flex justify-between items-center gap-5">
<FilterButtons dataFilter={""} flag="Artists" color="yellowColor" />
<FilterButtons dataFilter={""} flag="Albums" color="orangeColor" />
</div>
<div className="w-full flex justify-between items-center gap-5">
<FilterButtons dataFilter={filterByCategory} flag="Category" color="orangeColor" />
<FilterButtons dataFilter={filterByLanguage} flag="Language" color="yellowColor" />
</div>
Broadcast props
const FilterButtons = ({ dataFilter, flag, color }) => {
return (
<div className={`w-1/2 flex items-center justify-between px-4 py-2 border border-${color} text-${color} rounded-xl cursor-pointer`}>
<p className={`tracking-1 text-lg`}>{flag}</p>
<MdOutlineKeyboardArrowDown className={`text-4xl`} />
</div>
)
}
Usage in the component
The first block displays a field with a yellow border with black text and with orange texts and a white border
Result
I tried to divide into different variables and set conditions with different flags, nothing changes
You might be having some css specificity issue which is very common with tailwind. But tailwind has a workaround for this.
Use exclamation on the class you want to force a higher specificity for. Example (in your case):
!text-${color}

Not able to locate Hydration Error: Initial UI does not match what was rendered

I have been looking at this piece of code for over 2 days now, and i have not been able to locate my Hydration error. It is driving me crazy. Could some one maybe take a look at it for me? Are there any tips and tricks to spot these kind of errors more quickly, would love to know!
I'am using nextjs and using axios for the get resquest
These are the errors:
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
react-dom.development.js?ac89:19849 Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
export async function getStaticProps() {
try {
const res = await axios.get('https://open.data.amsterdam.nl/Festivals.json')
const events = res.data;
return {
props: {
events: events.slice(0, 10)
}
}
} catch (error) {
console.log(error)
}
}
function EventsCards({events}) {
return (
<div>
<a id="pressable-card max-w-md">
<div id="featured-event-container" className="bg-black rounded-md bg-opacity-20 bg-blur-sm max-w-xs shadow-lg">
<div id="event-banner">
<img className="max-w-lg w-full h-full" src={events.media[0].url }/>
</div>
<div className="text-white pl-2">
<h1 className="text-lg font-medium text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600">{events.title}</h1>
<a className="text-sm uppercase">{events.title}</a>
<a className="text-xs text-">Friday 20 Jan | 13:00 - 02:00</a>
</div>
<div className="py-2 px-2">
<p className="text-slate-200 font-normal border-[1px] py-[2px] px-[4px] rounded-lg border-slate-400 w-8 text-[8px]">Techno</p>
</div>
</div>
</a>
</div>
)
}
function Events({events}) {
return (
<div className="bg-gradient-to-t from-gray-500 to-gray-900 h-full bg-blur-sm pt-2">
<div className="max-w-6xl mx-auto">
<div className="px-8 ">
<div className="flex">
<h1 className="text-white font-regular opacity-100 tracking-wider sm:text-xl md:text-2xl">Featured events in Amsterdam</h1>
<div className="pl-2 my-auto">
<img className="rounded-full w-8 h-8 md:w-6 md:h-6 border-gray-400" src="https://www.fotw.info/images/n/nl.gif"></img>
</div>
</div>
<ul className="grid grid-cols-1 md:grid-cols-2 pt-4 md:w-full">
<div id="featured-wrapper" className="bg-black rounded-md bg-opacity-20 bg-blur-sm max-w-xs shadow-lg">
<a id="pressable-card max-w-md">
<div id="featured-event-container">
<div id="event-banner">
<img className="max-w-lg max-h-lg w-full h-full" src='https://d1as2iufift1z3.cloudfront.net/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaWpqIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--696c8f363a91d0501e8ae333fc9d42e5fd9c225f/ERT_HOLLAND_SIGNUP_banner%20(1).jpg?proxy=true'></img>
</div>
<div className="text-white pl-2">
<h1 className="text-lg font-medium text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-pink-600">El Row Town 2022 - Holland</h1>
<a className="text-sm uppercase">{events.title}</a>
<a className="text-xs text-">Friday 1 Jan | 11:00 - 04:00</a>
</div>
<div className="py-2 px-2">
<a className="text-slate-200 font-normal border-[1px] py-[2px] px-[4px] rounded-lg border-slate-400 w-8 text-[8px]">Techno</a>
</div>
</div>
</a>
</div>
<div className="text-red-400"><h1>test</h1></div>
</ul>
</div>
{/* Amsterdam Events */}
<div className="flex justify-center py-8">
<button className="text-[8px] uppercase font-medium rounded-md py-[8px] px-2 bg-white">see events in Amsterdam</button>
</div>
{/* All Events */}
<div className="mx-auto max-w-6xl w-full">
<h1 className="px-8 text-white font-regular tracking-wider text-xl md:text-2xl">Amsterdam</h1>
</div>
<div className="max-auto max-w-6xl">
<div className="grid grid-cols-1 md:grid-cols-3 pt-4 md:w-full w-full px-8 gap-4">
{events.map((event) => (
<EventsCards key={event.id} events={event} />
))}
</div>
</div>
</div>
</div>
)
}
export default Events;```
There are a couple of issues with your code that are causing issues:
Invalid markup (anchor tags inside other anchor tags, ul tags without li children).
You are passing the prop events to your <EventCard /> component (it should have a name that is different from the events array retrieved server-side)
You are using a event.id for your key prop when none exists (it should be event.trcid).
Here's a basic working version of your components:
export default function Events({ events }) {
return (
<>
{events.map((event) => (
<EventsCards key={event.trcid} event={event} />
))}
</>
);
}
function EventsCards({ event }) {
return <div>{event.title}</div>;
}
export async function getStaticProps() {
try {
const res = await axios.get(
'https://open.data.amsterdam.nl/Festivals.json'
);
const events = res.data;
return {
props: {
events,
},
};
} catch (error) {
console.log(error);
}
}
More often, it's best to start by getting the data on the page and then add in your additional content and styles.
It happens because you make some changes on the server side and save them before the Fast-Refresh completes hence causing a hydration error. You can manually reload the page after completing saving the changes or wait for Fast-Refresh to complete and then save your codes.

Accessing a variable set in one component file in another file React js

I am quite new to react and am trying to create a sports fixture application where when you click on one of the fixtures in the list it takes you to a new page with more things you can do for that fixture.
On my home page I render the list of popular fixtures which I have set in a JSON called popular.json. I have this coded so if I add or remove a fixture from popular.json then this will automatically be rendered by having my component set up as below
import fixtures from './variables/popular.json'
export const setFixture = (id, home, homeLogo, away, awayLogo, date, time, venue) => {
const match = { id: id, teamA: home, teamALogo: homeLogo, teamB: away, teamBLogo: awayLogo, date: date, time: time, stadium: venue }
}
export default function Example() {
return (
<div >
<div className="max-w-4xl mx-auto px-4 py-1 sm:px-6 sm:pt-20 sm:pb-24 lg:max-w-7xl lg:pt-10 lg:px-8">
<h2 className="text-4xl font-bold text-white tracking-tight">
Popular
</h2>
<ul
time="list"
className="grid grid-cols-1 py-10 gap-6 sm:grid-cols-2 lg:grid-cols-3"
>
{fixtures.map((fixture) => (
<li key={fixture.id} className="col-span-1 rounded-lg bg-white bg-opacity-70 hover:bg-gray-100 shadow">
<a href="/game" onClick={setFixture(fixture.home,fixture.homeLogo,fixture.away,fixture.awayLogo,fixture.date,fixture.time,fixture.venue)}>
<div>
<div className="-mt-px flex">
<div className="flex w-0 flex-1">
<div className="mx-auto py-5 flex-shrink-0 flex justify-center">
<img
className="h-16 w-16"
src={fixture.homeLogo}
alt="Logo"
/>
</div>
</div>
<div className="w-1"></div>
<div className="-ml-px flex w-0 flex-1">
<div className="mx-auto py-5 flex-shrink-0 flex items-center justify-center">
<img
className="h-16 w-16"
src={fixture.awayLogo}
alt="Logo"
/>
</div>
</div>
</div>
<div className="-mt-px items-center flex">
<div className="flex w-0 flex-1">
<div className="relative -mr-px inline-flex w-0 flex-1 items-center justify-center rounded-bl-lg border border-transparent py-4 text-3xl font-bold text-gray-600 hover:text-purple-600">
<span className="justify-center">{fixture.home}</span>
</div>
</div>
<div className="flex w-1">
<div className="justify-center flex w-0 flex-1">
<span className="text-4xl font-bold text-center text-gray-600 hover:text-purple-600 tracking-tight">
V
</span>
</div>
</div>
<div className="-ml-px flex w-0 flex-1">
<div className="relative inline-flex w-0 flex-1 items-center justify-center rounded-br-lg border border-transparent py-4 text-3xl font-bold text-gray-600 hover:text-purple-600">
<span className="justify-center">{fixture.away}</span>
...
and so on and it looks like this render of fixtures
When you click on one of these games it redirects to the /game page where I want to build add more stuff you can see about each game.
I want to know which game has been selected by the setFixture function which is called onClick of one of the games, and then I want to pass in the match variable to my new component (which is in a different .jsx file) so that I can render the game that has been selected on the new page.
I have tried to import the match variable from this file and the setFixture function in the new component file but cannot set my variables for the teams, date, venue etc. from this import and am just seeing many errors.
Can anyone help me with how this can be done? Recognizing which game has been selected and loading this into another file?
Thank you so much!
The usual approach to problems in React is to make use of Components. A component represents an object, and is provided a set of properties to allow that instance of the object to be represented.
So, even before going to your "next page" think about the Components that you could have on this "page" - each of the Fixtures you are representing can be a Component that takes properties that will help render the teams in that match. This will then lead to less repetition in each of your components - the Example() component will now render (for example) 6 Fixture() components.
Also, React is usually a Single Page Application. Whilst you're getting your basic application working you don't need to consider Routing just yet. Also, pages aren't "loaded"; components are re-rendered when Component properties ("props" for short) are updated. So, in the same page above you could have a Game() component that initially doesn't have any team props sent to it and behaves by not rendering until it has teams set.
You could use something like https://stackblitz.com/ to showcase what you have now, and it'd be easier to show how your code can be simplified.

3rd party Images gets broken in nextjs production environment

Images that get a response from API are showing broken on production env of next.js.
Here is my code
import Image from 'next/image';
//import PlaceHolderImage from "../public/images/placeholder.png";
interface IProps {
soldDate?: string;
price: string;
address: string;
bed: number;
bath: number;
cars: number;
sqm?: number | null;
image: any;
}
const PropertyCardInfo = (props: IProps): JSX.Element => {
return (
<div className="h-auto text-cpBlack border border-cpGreyLine mb-4">
<div className="w-full h-auto relative">
<Image
src={props.image}
alt={props.address}
width={360}
height={238}
layout="responsive"
/>
</div>
<div className="h-auto flex flex-col justify-between mt-1.5">
<div className="flex items-center justify-between pt-3.5 px-3.5">
<p className="font-semibold">{props.price}</p>
{props.soldDate && <p className="text-cpGrey text-sm">Sold {props.soldDate}</p>}
</div>
<a href="#" className="my-2 px-3.5 text-sm hover:text-cpOrange">
{props.address}
</a>
<div className="pb-3.5 px-3.5 flex text-sm font-semibold">
<p className="mr-2">
{props.bed}
<span className="ml-0.5">bed</span>
</p>
<p className="mr-2">
{props.bath}
<span className="ml-0.5">bath</span>
</p>
<p className="mr-2">
{props.cars}
<span className="ml-0.5">cars</span>
</p>
{props.sqm && (
<p className="mr-2">
{props.sqm}
<span className="ml-0.5">sqm</span>
</p>
)}
</div>
</div>
</div>
);
};
export default PropertyCardInfo;
I have whitelisted the domain and image URL domain in the next.config.js.
It also works well in development and local build environment.
But on deployment to UAT env, it show broken link and show the below error.
But if I pass same image through custom loader function then it worked.
const ImgLoader = ({ src }) => {
return props.image;
};
<Image
loader={ImgLoader}
src={props.image}
alt={props.address}
width={360}
height={238}
layout="responsive"
/>
Do I need to use custom loader for 3rd party images or Do I need to install sharp plugin ?
Please correct me if I am wrong.

Categories