How do I select my CSS module class using document.querySelector? - css

I want to be able to select styles.scrollValue using the document.querySelector()
import { useEffect } from "react";
import styles from "./Navbar.module.scss";
const Navbar = () => {
const handleScroll = () => {
document.querySelector(styles.scrollValue).innerHTML = scrollY;
};
useEffect(() => {
document.addEventListener("scroll", handleScroll);
return () => {
document.removeEventListener("scroll", handleScroll);
};
});
return (
<nav className={styles.navbar}>
<div className={styles.content}>
<h1 className={styles.scrollValue}>0</h1>
</div>
</nav>
);
};
Running this code I get an error:
TypeError: document.querySelector(...) is null
I know I can add a global class to that element doing this:
className={`${styles.scrollValue} scrollValue`}
But that would ruin the advantage of using CSS Modules.
Is there a way to select the CSS Module class without adding another one to it?

You need to select it as a class,
document.querySelector(`.${styles.scrollValue}`)
Calling styles.property returns a value such as the following,
scrollValue: '_src_styles_module__scrollValue'
So when you call document.querySelector it's looking for _src_styles_module__scrollValue which has no selector type such ., or # which makes it look for an element that would match <_src_styles_module__scrollValue> (in this case). Since there is no element with that name or the hashed name it will return null.
Working demo

Related

How to add transition effect when content changes in react using CSSTransition

const Component = () => {
const [newName, setnewName] = useState('');
const updateName = (max: number) => {
//logic to update newName
};
return (
<>
<div>{newName}</div>
</>
);
};
export default Component;
When ever the newName variable's value changes I want to add some effect in the ui for it. Is there any way that this can be done?
Yes. You can use the useEffect hook to achieve this, and add the newName state as a dependency.
For example, take a look at the following. I will demonstrate through console.log("hey, newName changed") every time the variable state changes.
const Component = () => {
const [newName, setnewName] = useState('');
useEffect(() => {console.log("hey, newName changed!"}, [newName])
const updateName = (max: number) => {
};
return (
<>
<div>{newName}</div>
</>
);
};
export default Component;
Import it with useState.
Now, you may ask "yes, but youre only consoling something out, not actually doing anything with the CSS transition". Rest assured, you can take a similar approach.
The useEffect hook is simply a function that watches for state change. From the callback function, just add your custom css transition class, or fire a function that changes the CSS.
As I am not sure what kind of transition effect you want as you did not specify it in your question, so forgive me for not being able to provide a specific example. I hope this helps you.
use useEffect and dependancy in to change state and using that state you can update class, and then write aniamtion css for that class , hope this will help...
import React from "react";
import "./App.css";
function App() {
const [newName, setnewName] = React.useState('Lorem');
const [transition, setTransition] = React.useState(false)
React.useEffect(()=>{
setnewName('ipsum')
setTransition(true)
},[newName])
return (
<>
<h1 classNane={`${transition?'animate':''}`} >{newName}</h1>
</>
);
}
export default App;

Using arbitrary runtime strings for Tailwind CSS class positioning

How can I specify a div's position from runtime data? Should I use some hook to set the className string? I find a lot of the time it's async issues that cause this kind of problem.
Anyway I was hoping someone could point me in the right direction, it's possible what I want to do isn't even supported by tailwind:
{timeRecord.clockedTimes.map((time, index) => {
let date = new Date(time.start);
let topOffset = getTopOffset(date).toFixed(4);
let stringOffset = `top-[${topOffset}%]`;
let className = "absolute " +stringOffset+" outline outline-red-400 w-1/2 left-1/2";
return (
<div className={className} >
{stringOffset}
</div>
)
})}
If I copy the text displayed inside the div by rendering the stringOffset from within the div and remove the composition of the className and just make it a static string with the runtime data copy and pasted it set's the right position.
Tailwind isn't built dynamically upon render. If you know what the value is before you compile you can include it or us something like cx to append a className, but you'll have to style in this case, you may need to play with the style prop a bit:
interface getTopOffsetProps {
timeDate: Date
}
const getTopOffset = ({ timeDate }: getTopOffsetProps) => {
return timeDate
}
interface ClockedTimes {
time: string
}
const ChildComponent = ({ time }: ClockedTimes) => {
const date = new Date(time)
const stringOffsetStyle = `${getTopOffset({ timeDate: date })}`
return (
<div className="absolute outline outline-red-400 w-1/2 left-1/2" style={{ top: stringOffsetStyle }}>
{stringOffset}
</div>
)
}
interface ParentComponentProps {
timeRecord: string[]
}
const ParentComponent = ({ timeRecord }: ParentComponentProps) => {
return (
<div>
{timeRecord.map((time, index) => {
<ChildComponent time={time} />
})
</div>
)
}

Change width of event in FullCalendar (React JS)

I like to change the width of an event in context of React JS.
Similiar questions described here:
How to edit width of event in FullCalendar?
Change Fullcalendar width
...
Unfortunately, in the quoted questions is nothing mentioned how to solve this in a react environment.
I figured it out how to do it. eventRender does no longer exist (v4) but instead different "event render hooks" (v5):
eventClassNames: Specifically for changing the .css of an event
eventContent: To inject content into the event
and others (see:https://fullcalendar.io/docs/event-render-hooks)
Now, depending what you want to achieve, there are two ways to do this in React JS. (Note: I used TypeScript)
Applying CSS change to all events
We can use styled to create our own .css definition for any event and use that as a wrapper (StyleWrapper)
import React from 'react';
import FullCalendar from '#fullcalendar/react';
import timeGridPlugin from '#fullcalendar/timegrid';
import styled from '#emotion/styled';
export interface ISampleProps {}
//our Wrapper that will go around FullCalendar
export const StyleWrapper = styled.div`
.fc-event {
width: 98px !important;
}
`;
//Reacct Functional Component
const Sample: React.FunctionComponent<ISampleProps> = (props) => {
const events = [
/*some events */
];
return (
<>
<div>
<StyleWrapper>
<FullCalendar
plugins={[timeGridPlugin]}
initialView="timeGridWeek"
events={events}
/>
</StyleWrapper>
</div>
</>
);
};
export default Sample;
Apply specific CSS to specific events
With this way, you can tell FullCalendar exactly how an event has to look like depending self-defined props you add to an event. Your self-defined props will be added to extendedProps which will be used in our event render hook eventClassNames
//same imports from earlier (but you don't need "styled" for this one)
const Sample: React.FunctionComponent<ISampleProps> = (props) => {
function eventAddStyle(arg: any) {
//all self-created props are under "extendedProps"
if (arg.event.extendedProps.demanding) {
return ['maxLevel']; //maxLevel and lowLevel are two CSS classes defined in a .css file
} else {
return ['lowLevel'];
}
}
const events = [
{
id: 'a',
title: 'This is just an example',
start: '2022-03-19T12:30:00',
end: '2022-03-19T16:30:00',
backgroundColor: '#74AAEB',
demanding: true //our self-created props
},
{
id: 'b',
title: 'This is another example',
start: '2022-03-17T08:00:00',
end: '2022-03-17T11:30:00',
demanding: false // our self-created props
},
];
return (
<>
<div>
<FullCalendar
plugins={[timeGridPlugin]}
initialView="timeGridWeek"
eventClassNames={eventAddStyle}
events={events}
/>
</div>
</>
);
};
export default Sample;

In React, how can I apply a CSS transition on state change, re-mount, or re-render?

Say I have a React functional component with some simple state:
import React, { useState } from 'react'
import { makeStyles } from "#material-ui/core"
export default function Basket() {
const [itemCount, setItemCount] = useState<number>(0)
return (
<div>
<Count count={itemCount} />
<button onClick={() => setItemCount(itemCount + 1)}>
Add One
</button>
</div>
)
}
function Count({count}: {count: number}) {
const classes = useStyles()
return (
<div className={classes.count}>
{count}
</div>
)
}
const useStyles = makeStyles({
count: {
backgroundColor: "yellow",
transition: "backgroundColor 2s ease" // ???
}
}
I want the Count component to apply a property whenever the count changes and then remove it again; say, turn on backgroundColor: yellow for 2 seconds and then gradually fade it over 1 second. What's the simplest way to achieve this?
Note that presumably this could be either triggered by a state change on the parent or by a re-rendering of the child. Alternatively, I could add the key property to <Count/> to force a re-mount of the child:
<Count
key={itemCount}
count={itemCount}
/>
Any of those would be acceptable; I'm looking for the simplest, cleanest solution, hopefully one that doesn't require additional state and is compatible with Material-UI styling APIs.
Just an idea.
const Component = () => {
useEffect(() => {
// will trigger on component mount
return () => {
// will trigger on component umount
}
}, [])
}
...
document.getElementById('transition').classList.add('example')
You can use useEffect along with useRef containing a reference to the element or directly getting it with document.getElementById and then update the transition class that way in component mount/unmount. Not sure if it'll work, I haven't tested it myself.

using className in react

So what's the best pratice for using className in react. In specific multiple class names. I'm reading through the documentation and I don't really get a clear answer. I've seen things like:
const divStyle = {
color: 'blue',
backgroundImage: 'url(' + imgUrl + ')',
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}
but is there a way for me to do something like this?
import React from 'react';
import ReactDOM from 'react-dom';
import './css/landing.css';
import './css/w3.css';
class Home extends React.Component {
const homeClasses = 'bgimg-1 w3-display-container w3-opacity-min';
render() {
return (
<div className={homeClasses}>
<h1>SUP</h1>
</div>
);
}
}
ReactDOM.render(
<Home />,
document.getElementById('root')
);
or even just list then out in the class name section?
It depends what your component should/will do.
If your component is fairly static you will want to use a built in style like your first example:
const mystyle = {
width: '100%',
...
}
<div style={mystyle}>...</div>
However, there are better ways that allow your component to be more dynamic for re-use, for instance using a class method to generate the style from props passed to it, like in this render function:
render() {
// User's preference or Default Style:
const defaultStyle = {
width: this.props.style.width || '100%',
height: this.props.style.height || '100%',
}
//if this.props.className doesn't exist use mycssclass
const defaultClassName = this.props.className || 'mycssclass'
return (
<div className={defaultClassName} style={defaultStyle}>...</div> )
Following this logic you can use the ternary operator to change the css class name based on props. A common solution is use an isActive state property and use it to determine which class should be used.
render() {
const activeClassName = this.props.className + ' mycomponent-active'
return (
<div className={this.props.isActive ? activeClassName : this.props.className} style={ this.props.style }
</div>);
}
Another common, but complex way to set your component's style is to use a function that will return a given style object, and use it like the first example.
Ultimately, you should decided whether you would like your component to be styled by the designer/user or should look the same no matter where it is used... if it is styled by the designer, just expose the CSS class name from props to the component or define a default:
<div className={this.props.className || 'someclassName'}>...</div>
otherwise, use an example above.
Yes, you can do this! Take a look at the snippet below:
class Example extends React.Component {
cssClasses = 'demo demo2';
render() {
return (
<div className = { this.cssClasses }>
Hello World
</div>
);
}
}
ReactDOM.render( <Example/> , document.getElementById('app'));
.demo {
color: blue
}
.demo2 {
font-size: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
Your error was the definition of the homeClasses. You can't declare it like
const homeClasses = '...';
Because, on the way that you did, homeClasses is a property of your component. You should not use const. Just:
homeClasses = '...';
And you forgot to use the this reference, because the homeClasses is an attribute of your component.
<div className={this.homeClasses}>
<h1>SUP</h1>
</div>
Exists and one away for this problem. You can use and read this data from file (example data.json) where can use this data like props of that.

Resources