How to render different style css on same component? - javascript

I have react component which is a button and I render this component three times. I want to add some CSS on the second component but I don't know how. I tried to add some class names, but then I can't figure it out where to put this style in the CSS.
I can change css in element.style in dev tools but can't in project.
import './App.css';
import './flow.css';
import './neonButton.css';
import GlowBox from './GlowBox';
import NavBar from './NavBar';
function App() {
return (
<div>
<div className='divBut'>
<NavBar></NavBar>, <NavBar className='drugi'></NavBar>,<NavBar></NavBar>
</div>
<GlowBox></GlowBox>
</div>
);
}
export default App;
import styled from 'styled-components';
const NavBar = (props) => {
return (
<div>
<Container>
<a class='neon'>Neon</a>
</Container>
</div>
);
};
const Container = styled.div`
background-color: transparent;
`;
export default NavBar;
I try to add props to component
<!-- begin snippet: js hide: false console: true babel: false -->
and then add a type to a component like this
const NavBar = (type) => {
return (
<div>
<Container>
<a class={`neon ${type}`}>Neon</a>
</Container>
</div>
);
};
<NavBar></NavBar>, <NavBar type='drugi'></NavBar>,<NavBar></NavBar>
but nothing is change.

You have props that you don't use, this is a good simple read on How to Pass Props to component, you can adjust this to other needs, this is example...:
import styled from 'styled-components';
const NavBar = ({class}) => {
return (
<div>
<Container>
<a class={class}>Neon</a>
</Container>
</div>
);
};
const Container = styled.div`
background-color: transparent;
`;
export default NavBar;
...
import './App.css';
import './flow.css';
import './neonButton.css';
import GlowBox from './GlowBox';
import NavBar from './NavBar';
function App() {
const NavStyles = {
className1: 'neon',
className2: 'drugi'
};
return (
<div>
<div className='divBut'>
<NavBar class={NavStyles.className1}></NavBar>, <NavBar class={NavStyles.className2}></NavBar>,<NavBar class={NavStyles.className1}></NavBar>
</div>
<GlowBox></GlowBox>
</div>
);
}
export default App;

Edit: Given that you have edited your question I have new information for you.
1.) You can't use the reserved word class in React, because class means something different in Javascript than it does in html. You need to replace all instances of class with className.
2.) Did you notice how in the devtools on your button it says the className says: neon [object object]?
You should use a ternary operator to handle the cases where you don't pass the type prop.
ex.) class={neon ${props?.type !== undefined ? type ''}}
3.) You are trying to apply a className to a component, which does not work. The className attribute can only be applied directly to JSX tags like h1, div, etc. Use a different prop name, then you can use that to decide the elements className.

Related

How to apply css for a class in react component?

I am a new react-js learner and I am having a hard time adding css to my classes that I have inside my react component.
Here is the current code:
import React from 'react';
const Home = () => {
return (
<>
<div class="container">
<h1 class="mainHeader">Home</h1>
<h2>helloo</h2>
</div>
</>
);
};
.container {
// CSS would go here
}
export default Home;
In just HTML and CSS, I was able to apply css on the container div class by just using '.' and whatever the class name was. However, this is giving me an error.
Put the css in its own file, with a .css extension, then import it. Assuming you used create-react-app to set up your project, it will already have appropriate configuration for importing css files. Additionally, you need to use className for the prop, not class
// In a new file home.css:
.container {
// css goes here
}
// In the file you've shown:
import React from 'react';
import './home.css';
const Home = () => {
return (
<>
<div className="container">
<h1 className="mainHeader">Home</h1>
<h2>helloo</h2>
</div>
</>
);
};
export default Home;
Or you can declare it in json format or like you would an object, not in CSS form. Treat it as you are writing in js, which you actually are. See the edit below:
import React from 'react';
const Home = () => {
return (
<>
<div style={container}>
<h1 className="mainHeader">Home</h1>
<h2>helloo</h2>
</div>
</>
);
};
const container = {
// CSS would go here
color: 'red',
background: 'blue'
}
export default Home;

React Props not passing down to children components?

I am trying to learn React so please bear with me!
I am following a tutorial to help me understand react and how you can pass down components.
I am trying to pass props down 2 levels, but when I render the code on the third element, nothing appears on the page. Using React Dev tools on chrome, it seems that the props are loading on the Tweets.js component rather than the Tweet.js component.
Can anybody tell me whats wrong? The order is App.js > Tweets.js > Tweet.js
For ref, I am following the following tutorial, it is around the 15 min mark.
React State and Props | Learn React For Beginners Part 4
App.js
import './App.css';
import Tweets from './components/Tweets';
import React from 'react';
function App() {
const name=["Name1", "Name2", "Name3"];
const age=["21", "22", "24"]; /* Data is created here */
return (
<div className="App">
<Tweets me={name} age={age} />{/*Data is added to component*/ }
</div>
);
}
export default App;
Tweets.js
import Tweet from './Tweet';
const Tweets = (props) => (
<section>
<Tweet />
</section>
);
export default Tweets;
Tweet.js
const Tweet = (props) => (
<div>
<h1>{props.me}</h1>
<h1>{props.age}</h1>
</div>
);
export default Tweet;
You would need to transfer props through your Tweets component:
const Tweets = (props) => (
<section>
<Tweet {...props} />
</section>
);

Apply inline style to an element in React from a child element

I am still very new to React and I am trying to recreate a navigation bar that was originaly made with HTML, CSS and JS.
I have a Layout component and a Navbar component. In the Navbar component I have a button that when clicked should apply an inline style or a CSS class to the <main>{children}</main> element in the Layout component.
The Navbar element is used inside the Layout element, so I am wondering if this is even possible?
layout.js
import React from "react"
import { useStaticQuery, graphql} from "gatsby"
import Navbar from "./navbar"
const Layout = ({ location, title, children }) => {
const data = useStaticQuery(graphql`
{
site {
siteMetadata {
menuLinks {
link
name
}
}
}
}
`)
return (
<div>
<Navbar pages={ data.site.siteMetadata.menuLinks } />
<main>{children}</main>
</div>
)
}
export default Layout
navbar.js
import React, { useState } from "react"
import { Link } from "gatsby"
import styles from "./styling/navbar.module.less"
const Navbar = ( props ) => {
const [navbarState, setNavbarState] = useState(false);
let toggleNavbar = () => {
console.log("Navbar toggle - Activated")
setNavbarState((navbarState) => !navbarState)
}
window.addEventListener('resize', windowResized)
return (
<nav id={"navigation-bar"}>
<div className={`${styles.navLinks} ${navbarState? styles.navActive:""}`}>
{props.pages.map((page, index) => (
<Link key={page.name} className={`${styles.navLink} ${styles.navLinkHoverEffect} ${navbarState? styles.navAnimate:""}`}
style={{animationDelay: `${index / 7 + 0.5}s`}} to={page.link}>
{page.name}
</Link>
))}
</div>
<div className={`${styles.burger} ${navbarState? styles.toggle:""}`} onClick={toggleNavbar}>
<div className={styles.line1}></div>
<div className={styles.line2}></div>
<div className={styles.line3}></div>
</div>
</nav>
)
}
export default Navbar
Sure it's possible. When you want the child, Navbar, to change something in the parent (normally state) you can pass a function down. In Layout:
const [classes, setClasses] = useState('');
const setClassNames = (classnames) => {
setClasses(classnames)
}
Pass this function down to the child as a prop.
<Navbar pages={ data.site.siteMetadata.menuLinks } setClassNames={setClassNames} />
When the action occurs on the child, say an onClick event then call that function with the classes string you want to set on main.
Then in your parent component, Layout change the line to:
<main className={classes}>{children}</main>
Of note, the way it's currently setup you could just pass the setClasses to Navbar but I used a new function to just to show a more common scenario when you have to customize anything. Also you should use useCallback on the function setClassNames in Layout if you don't want Navbar to re-render every time.
Feel free to leave a comment with questions.

Importing FontAwesome icons by string array in React.js

I'm having an array of sidebar elements in my React.js project where each element is represented as object which among others has its own FontAwesome icon defined as string, like e.g. fa-phone. Now there's a problem with FontAwesome's integration into React.js; each icon has to be separately imported and added to the library, according to their manual.
import * as React from 'react';
import { library } from '#fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
interface SidebarElement {
fa: string,
href: string,
title: string
}
interface SidebarElements {
elements: SidebarElement[]
}
export default class Sidebar extends React.Component<SidebarElements, {}> {
render() {
const elements = this.props.elements.map((element, key) => {
// tweak icon name so it matches component name...?
...
// the two lines below obviously won't work
import { element.fa } from '#fortawesome/free-solid-svg-icons'
library.add(element.fa);
return (
<li key={key} className="nav-item">
<a className="nav-link" href={element.href}>
<FontAwesomeIcon icon={element.fa} />
<span>{element.title}</span>
</a>
</li>
);
})
return (
<ul className="sidebar navbar-nav">{elements}</ul>
);
}
}
But the solution above obviously won't work, since imports have to happen at top-level and won't take the component name from a variable. Are there any alternative ways to import icons without exactly knowing them from the beginning? Or am I forced to import all icons at the same point I'm defining my sidebar elements?
I went with this same issue on a personal project I'm building. The first problem I found was related to how dynamically rendering the icon from a query?
Main app container:
import React from "react"
import Header from "../components/header"
import Navigation from "../components/navigation"
import Footer from "../components/footer"
import containerStyles from "./styles.module.less"
import { library } from "#fortawesome/fontawesome-svg-core"
import { fab } from "#fortawesome/free-brands-svg-icons"
library.add(fab)
const IndexPage = ({ data }) => (
<div className={containerStyles.home}>
<div className={containerStyles.menu}>
<Header />
<Navigation />
</div>
<Footer />
</div>
)
export default IndexPage
Also, my icons are part of the free-brand version so imported them to the library.
So the first thing I did was to import the library and create a pair of null variables on my child component, one for the prefix and the other one for the icon itself:
In my project, I'm consuming the data from an API endpoint, the query I built to get the information is the following:
Theoretically, all was set just for mapping the array and render each item as we normally do:
<FontAwesomeIcon
icon={[
(faprefix = document.node.prefix),
(faicon = document.node.icon),
]}
size="lg"
/>
But the child component was rendering nothing. Why was this? Simply because of both document.node.prefix and document.node.icon are returning strings so when the component mapped the data from the array, it ended trying to render something like this:
<svg data-prefix="'fab'" data-icon="'github'" >
Please note the single quotation mark wrapping the string
My solution to this was to use a replace() method with a regex to remove the wrapping quotations marks:
<FontAwesomeIcon
icon={[
(faprefix = document.node.prefix.replace(/'/g, "")),
(faicon = document.node.icon.replace(/'/g, "")),
]}
size="lg"
/>
Child footer component
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import containerStyles from "../pages/styles.module.less"
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome"
let faicon = null
let faprefix = null
const Navigation = ({ data }) => (
<StaticQuery
query={graphql`
query FooterTemplate {
allStrapiLink {
edges {
node {
id
icon
url
prefix
}
}
}
}
`}
render={data => (
<>
<footer>
<p>Freddy PolanĂ­a {new Date().getFullYear()}</p>
<div className={containerStyles.links}>
{data.allStrapiLink.edges.map(document => (
<div key={document.node.id}>
<a
href={document.node.url}
rel="noopener noreferrer"
target="_blank"
>
<FontAwesomeIcon
icon={[
(faprefix = document.node.prefix.replace(/'/g, "")),
(faicon = document.node.icon.replace(/'/g, "")),
]}
size="lg"
/>
</a>
</div>
))}
</div>
</footer>
</>
)}
/>
)
export default Navigation
Now my icons are rendering from the endpoint's data. I hope this could help to solve your issue.

CSS modules pass property as styles property

I'd like to add a custom class to my Button component in app I'm learning react on.
In my Form.js I have
import React, {Component} from 'react';
import Button from './Button';
import styles from '../css/LoginElements.css';
class Form extends Component {
render() {
const click = this.props.onSubmit;
return(
<div className={styles.form}>
<Button
name="Register"
className="register"
onClick={click} />
</div>
);
}
}
export default Form;
And in the Button.js I have
import React from 'react';
import styles from '../css/LoginElements.css';
const Button = ({name, onClick, className }) => (
<div className={styles.wrapper}>
<div className="field">
<div className={className? styles.className : styles.button} onClick={onClick}>{name}</div>
</div>
</div>
);
export default Button;
The problem is that styles.className will work if I put .className in my LoginElements.css file, and not .register, as I would like.
What do I need to do to use the class name from the button property as a class? And not just register but so that it's like LoginElements__register__34Kfd (locally scoped)?
Maybe I'm not reading this correctly, but I think the problem is that you're using dot notation to access the className from styles instead of brackets.
Can you update Button.js to
<div className={className? styles[className] : styles.button}
Dot notation will not recognize className as a variable but instead will treat it literally as the property name

Categories

Resources