onClick event not firing in my styled component in my react app - javascript

I'am trying to trigger an onCick event that i passed to my style component icon tag but for some reason the event does not get triggered when the icon is clicked. I've tried raping it in a div and passing the onClick event to the div instead but still get the same result.
here is the code:
import React from "react";
import { useState } from "react";
import StyledNav, {NavbarhamButton} from "./style/Navbar.styled";
const Navbar = () => {
const [NavOpen, setNavOpen] = useState(false);
return (
<StyledNav>
<NavbarhamButton
className="fas fa-bars"
onclick={() => setNavOpen(!NavOpen)}
/>
</StyledNav>
);
};
export default Navbar;
Here is the styled components:
import { Link } from "react-router-dom";
import styled from "styled-components";
import { theme } from "../../theme";
const StyledNav = styled.div``;
export const NavbarhamButton = styled.i`
position: absolute;
top: 0;
left: 0;
margin: 1rem;
font-size: 2rem;
color: white;
#media screen and (min-width: 600px) {
display: none;
}
z-index: 2;
`;
I just started to use style components of recent so am still trying to wrap my head around it please correct me if am doing something wrong thanks.

Try changing the prop to onClick for <NavbarhamButton />. You may also need to use a base component other than i. So you might want to try styled.button instead of styled.i.

Related

How can I make this scroll To Top upon re-rendering while keeping the headers reactive functionality?

This is alot of code but it is the minimal way that I could think of reproducing my problem.
view in sandbox: https://codesandbox.io/s/silly-kare-j0kmz
I would like the header bar to hide upon scrolling. The problem is everytime I click on a box to go to another route, or click header to come back to the home route, the scroll bar stays where it was before. That is everytime I move from route to route, the scrollbar does not move to the top.
I was able to fix this problem with the scrollToTop code, But in order to make it scroll to the top, I need to remove "overflow-y" from App.css, which stops my header from reacting onScroll.
I came to realize this is because window is perhaps a BOM object and only targets the browser window itself, not div class which I have assigned onScroll to.
So it seems I can do either OR, but not both functions together. I would like both to happen, The scrolToTop on location change AND to keeep the Header Reacting to the onScroll method. How can I do that?
App.js ---------------------------------------------------
Provides routing to First.js and Second.js. Also has the onScroll method. That is when you scroll up, the header appears, and when you scroll up the header disapears. Along with some routing to 2 simple components.
import './App.css';
import {useState, useEffect, useRef} from 'react';
import { Route, Routes} from 'react-router-dom';
import Second from "./Second/Second";
import First from "./First/First";
import Header from './Header/Header';
import ScrollToTop from './ScrollToTop/ScrollToTop'
function App() {
const prevScrollY = useRef(0);
const [goingUp, setGoingUp] = useState(true);
const [HeaderisVisible, setHeaderIsVisible] = useState(0);
const onScroll = (e) => {
const currentScrollY = e.target.scrollTop;
if (prevScrollY.current < currentScrollY && goingUp) {
setGoingUp(false);
}
if (prevScrollY.current > currentScrollY && !goingUp) {
setGoingUp(true);
}
prevScrollY.current = currentScrollY;
console.log(goingUp, currentScrollY);
};
return (
<div className="App" onScroll = {onScroll}>
<ScrollToTop/>
<Routes>
<Route path = '/' exact element = {<First GoingUp = {goingUp}/>}/>
<Route path = '/second' element = {<Second GoingUp = {goingUp}/>} />
<Route path = '*'>
NOT FOUND
</Route>
</Routes>
</div>
);
}
export default App;
Header.js -------------------------------------------------
Header takes props from the state initialized in App.js containing a true or flase variable. and uses that in a conditional to either show or hide the header. Also on clicking the header you go back to the home page.
import './Header.css';
import {useState, useEffect} from 'react';
import {Link} from 'react-router-dom';
function Header(props) {
const [HeaderisVisible, setHeaderIsVisible] = useState(0);
useEffect(() => {
if(props.GoingUp == true){
setHeaderIsVisible(0);
}else{
setHeaderIsVisible(-199);
}
}, [props.GoingUp]);
return (
<Link to = '/'><div className = "Header"
style = {{
top: `${HeaderisVisible}px`
}}>
</div> </Link>
);
}
export default Header;
First.js --------------------------------------------------
First is a simple component that just displays some divs. Each black div will route the the second page.
import './First.css';
import {Link} from 'react-router-dom';
import Header from '../Header/Header';
function First(props) {
return (
<div className="First">
<Header GoingUp = {props.GoingUp}/>
<Link to = '/second'><div className = "entity"></div></Link>
<Link to = '/second'><div className = "entity"></div></Link>
<Link to = '/second'><div className = "entity"></div></Link>
<Link to = '/second'><div className = "entity"></div></Link>
<Link to = '/second'><div className = "entity"></div></Link>
</div>
);
}
export default First;
Second.js -------------------------------------------------
Second is a simple component that just displays some red divs.
import './Second.css';
import { Route, Routes, Link} from 'react-router-dom';
import Header from '../Header/Header';
function Second(props) {
return (
<div className="Second">
<Header GoingUp = {props.GoingUp}/>
<div className = "entity2"></div>
<div className = "entity2"></div>
<div className = "entity2"></div>
<div className = "entity2"></div>
<div className = "entity2"></div>
</div>
);
}
export default Second;
ScrollToTop.js --------------------------------------------
Gets the location via the url search path, and scrolls to the top of the page on every search.
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop(props) {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return null;
}
First.css
-----------------------------------
.entity{
height: 200px;
margin: auto;
width: 200px;
border: 2px solid black;
background-color: black;
margin-top: 200px;
}
Second.css
-------------------------------------
.Second{
background-color: lightgreen;
}
.entity2{
height: 200px;
margin: auto;
width: 200px;
border: 2px solid black;
background-color: red;
margin-top: 200px;
}
Header.css
------------------------------------
.Header{
background-color: brown;
height: 200px;
position: fixed;
width: calc(100% - 17px);
}
App.css
-------------------------------------
html{
margin: 0;
}
body{
margin: 0;
}
.App{
overflow-y: auto;
background-color: lightblue;
height: 100vh;
}
I was able to solve my problem by replacing window.scrollTo(...) with the following: props.refProp.current.scrollTop = 0; inside of scrollToTop function.
export default function ScrollToTop(props) {
const { pathname } = useLocation();
useEffect(() => {
props.refProp.current.scrollTop = 0;
}, [pathname]);
return null;
}

Unable to apply styles to styled-component element in Reactjs

I'm trying to wrap a component with a styled-component div and apply some styles. However, for some reason, the styles aren't being applied, even though the ostensibly correct wrapper that is expected to be rendered is being rendred.
CodeSandbox
What am I doing wrong here?
You just forgot to pass the className props, see here:
const Component = ({ className }) => (
<div className={className}>Hello World!</div>
);
https://codesandbox.io/s/optimistic-lumiere-cq8gt?file=/src/App.js
I hope I helped you. Have a good day.
EDIT: Check the docs here
You need to container Component with styled.{tag} or styled(Component)
And then use that Container component to wrap main component.
import React from "react";
import "./styles.css";
import styled from "styled-components";
export default () => <Component />;
const Component = () => <StyledDiv>Hello World!</StyledDiv>;
const StyledDiv = styled.div`
font-size: 10rem;
color: red;
display: flex;
justify-content: center;
align-items: center;
`;
Check here: https://codesandbox.io/s/dank-hill-h8rbc?file=/src/App.js:128-189

Using a styled component's rules within `createGlobalStyle`

New to styled components and am wondering if someone might have some advice on how to use a styled component's rules within a call to createGlobalStyle?
The below example is working, but I feel that it is not a great solution as componentStyle.rules is not in the official api docs.
// A styled component
import Modal from '../Modal'
import styled, { createGlobalStyle } from 'styled-components'
const StyledComponent = styled(Modal)`
background-color: pink;
`
createGlobalStyle`
// this div is mounted outside of the React root
.modal-from-external-library {
${StyledComponent.componentStyle.rules}
}
`
Not sure if what I was trying to do was possible, but I ended up solving the problem by exporting the css from the Modal using the css function of styled components.
// Modal.js
const styles = css`
// styles here
`
export default styled.div`
${styles}
`
// ... later
const GlobalStyles = createGlobalStyle`${styles}`
render() { return (<GlobalStyles {...props} />) }

Styled-component object can't observe mobx changes

I would like an HOC generated by styled-components to re-render when one of its properties get changed. I'm using MobX for change detection.
This doesn't respond to changes, I think I understand why. The question is if there is a simple workaround to make it work.
const DemoComponent = observer(styled.div`
background-color: ${props => props.myObject.myObservableIsTrue ? 'red' :
'green'};
`);
It's hard to tell by this little snippet, but one of my guesses would be you are not injecting any store, so currently, no store is being connected to your component.
here's a simple example of how I used styled-components with mobx if it helps:
EDITED:
I've updated the code example.
Do you know the Container / Presentational pattern?
This was the missing link.
In order to keep your renders as little as possible
you need to separate your stateful component from each other.
Spread them across a Container component (aka Dumb Components)
This way you separate state concerns and render only the component with the changed state.
UPDATED:
https://codesandbox.io/s/zxx6o2pq3l
Sorry!!! A bit of a hack job, but attempt to bring your entire code inside the #inject("store") class:
import React from "react";
import { observer, inject } from "mobx-react";
import styled, { css } from "styled-components";
#inject("store")
#observer
export default class OtherComponent extends React.Component {
render() {
const MyWrapper = (store) => {
const Wrapper = styled.div`
border: 1px solid black;
display: flex;
justify-content: space-between;
color: ${({ color }) => color};
border: 2px solid ${({ color }) => color || "black"};
padding: 10px;
margin-bottom: 10px;
`;
return (
<Wrapper {...store}>
styled-component
<button onClick={store.changeColor}>change color</button>
</Wrapper>
);
}
const { store } = this.props;
return (
<div>
{
MyWrapper(store)
}
</div>
);
}
}
Mobx is actually read like this: #inject("store") #observer export default class...
So it really an extension of an extended component; only wrapped variables will apply!

Passing props from react-cosmos to styled-components

I have the following component where I have applied the css using styled-components:
import styled from 'styled-components'
// square-block css can be re-written as a styled-component(???)
const SquareBlock = styled.div`
width: 100%;
height: 100%;
background-color: ${props => props.color};
`
export default SquareBlock
I would like to use the following fixture with react-cosmos to adapt the background-color of the component based on the props:
import { COLORS } from '../../../constants/tetronimo'
export default {
color: COLORS.I
}
In the React developer tools I noticed that the component PropsProxy had a fixture prop which has the color property:
JSON.stringify($r.props.fixture, null, 2)
{
"color": "#3cc7d6"
}
How can I ensure that props are passed correctly to react-cosmos?
Props need to be placed under fixture.props in the latest version of React Cosmos, but you seem to have already figured this out. Does this solve your problem?

Categories

Resources