how to change styled(component) element - reactjs

Having trouble changing the "section" into a div without touching the BaseGrid, the BaseGrid is in a different folder component, and I'm just importing it. If I use the forwardedAs='div' or as='div', it will render as a div but will not pass the default values that I still need from the BaseGrid.
How can I make it as a div and still get all the props that i need from the BaseGrid styled.section
const BaseGrid = styled.section `
....style here
`;
import {BaseGrid} from '/somefolder';
const SectionGrid = styled(BaseGrid).attrs({as: 'div'})`
..style here
`;
const SectionGrid = ({ forwardedAs, className, children, ...rest }: SectionGridProps) => (
<BaseGrid forwardedAs={'div'} className={addClassName('section-grid', className)} {...rest}>
{children}
</BaseGrid>
);
const app () => {
return
<>
<SectionGrid />
</>
};
I'm trying to implement these but still not working

import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import "./styles.css";
const ExtendMe = styled.div`
color: red;
border: 1px solid red;
`;
const SomeImg = styled(ExtendMe).attrs({
as: "img"
})`
margin: 2em;
`;
const SomeDiv = styled(ExtendMe)`
margin: 3em;
`;
function App() {
return (
<div className="App">
<SomeImg src="data:image/jpeg;base64,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" />
<SomeDiv>A div</SomeDiv>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
You can refer: https://www.styled-components.com/docs/api#as-polymorphic-prop.

Related

how can i fix use location error in my react app?

import styled from "styled-components";
import Navbar from "../componant/Navbar";
import Announcement from "../componant/Announcement";
import Products from "../componant/Products";
import Newsletter from "../componant/Newsletter";
import Footer from "../componant/Footer";
import { mobile } from "../responsive";
import { useLocation } from "react-router";
import { useState } from "react";
const Container = styled.div``;
const Title = styled.h1`
margin: 20px;
`;
const FilterContainer = styled.div`
display: flex;
justify-content: space-between;
`;
const Filter = styled.div`
margin: 20px;
${mobile({ width: "0px 20px", display: "flex", flexDirection: "column" })}
`;
const FilterText = styled.span`
font-size: 20px;
font-weight: 600;
margin-right: 20px;
${mobile({ marginRight: "0px" })}
`;
const Select = styled.select`
padding: 10px;
margin-right: 20px;
${mobile({ margin: "10px 0px" })}
`;
const Option = styled.option``;
const ProductList = () => {
const location = useLocation();
const cat = location.pathname.split("/")[2];
const [filters, setFilters] = useState({});
const [sort, setSort] = useState("newest");
const handleFilters = (e) => {
const value = e.target.value;
setFilters({ ...filters, [e.target.name]: value, });
};
return (
{cat} Filter Products: Color white black red blue yellow green Size XS S M L XL Sort Products:
<Select onChange={(e) => setSort(e.target.value)}> Newest Price (asc) Price (desc)
);
};
export default ProductList;
The error useLocation() may be used only in the context of a <Router> component. is caused by an invariant violation. The error message is clear enough, you've not rendered the ProductList component using the useLocation hook within a routing context provided by a Router.
This is react-router-dom version 6
useLocation
export function useLocation(): Location {
invariant(
useInRouterContext(),
// TODO: This error is probably because they somehow have 2 versions of the
// router loaded. We can help them understand how to avoid that.
`useLocation() may be used only in the context of a <Router> component.`
);
return React.useContext(LocationContext).location;
}
You should have a single router wrapping your App component to provide a routing context to the entire app, which would including this ProductList component.
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById('root')
);
Based on some comments of yours from the other answer it appears you are mixing up the RRDv5 and RRDv6 components. V6 has no Switch component, it was replaced by a Routes component.
Check the installed version of react-router and react-router-dom:
npm run list react-router react-router-dom
If you have v5 installed, follow the v5 docs, otherwise if you've v6 installed, see the v6 docs. The upgrading from v5 migration guide will detail the differences between the two versions.
Wrap your app in Routes component.
import React from "react";
import {
BrowserRouter as Router,
Routes,
} from "react-router-dom";
const AppWrapper = () => {
return (
<Router>
<Routes>
<App />
</Routes>
</Router>
);
};
export default AppWrapper;

React styled-components how styled declared component

I will try explain one more time my problem for better undestanding .
I need styled component whose I wish he was simultaneously method when i can inject props .
I created easier code for this example :
import React from "react";
import styled from "styled-components";
import "./App.css";
const styledInput = styled.input`
width: 300px;
height: 300px;
border: 2px solid black;
`;
const Input = props => {
return <styledInput type="text" />;
};
const App = props => {
return (
<div>
Text : <Input val={1} />
</div>
);
};
export default App;

In a React application, how do I use .contains() on a styled component?

I have this click handler:
clickHandler = event => {
if (this.node.contains(event.target)) {
console.log("clicked inside");
return;
}
console.log("clicked outside");
};
My List component is defined like this;
const List = styled.ul`
margin: 0;
padding: 5px 0;
list-style: none;
border-top: 1px solid #789;
color: black;
font-weight: 500;
`;
Then in my render function I have this;
<List ref={node => (this.node = node)} key={index}>
When my click handler is executed, I get the following error:
TypeError: _this.node.contains is not a function
If I console log this.node I can see it is a styled component, but it does not have a ref nor an innerRef property, so I don't see how I can access the underlying node element so that I can use .contains()
This is what I have in package.json:
"styled-components": "^3.4.5",
When you pass the ref to your styled-component, you should still be able to access the inner-node element. Below we will use the clickHandler as a call-back to a window event-listener.
Working sandbox: https://codesandbox.io/s/amazing-surf-kivtr
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import "./styles.css";
const List = styled.div`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
class App extends React.Component {
node = null;
componentDidMount() {
window.addEventListener("click", this.clickHandler);
}
clickHandler = event => {
if (this.node.contains(event.target)) {
console.log(this.node);
console.log("clicked inside");
return;
}
console.log("clicked outside");
};
render() {
return (
<div>
<List ref={ref => (this.node = ref)}>
<div>Example</div>
</List>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Is there a way to declare styled component with different main elements?

I need to create 2 similar styled components, which will share their styling but use different HTML element.
There is a way to do in runtime with "as" property (), but I have a specific exports which I need to use the default but I need for it to be in a way without using it so the Link styled component be a "styled.a" and StyledLink component to be "styled.span", I tried to do something like:
export const StyledLink = styled.span(`
color: ${props => props.theme.colors.mainLinkColor};;
text-decoration: underline;
&:hover {
color: ${props => props.theme.colors.textAccent};
text-decoration: underline;
}
`);
export const Link = <StyledLink as={RRLink} />;
That is obviously not working... So is there a way for a Link to mimic StyledLink styles but use an "a" tag instead of "span"?
Simply import and use css from styled-components like so:
import React from "react";
import ReactDOM from "react-dom";
import styled, { css } from 'styled-components';
const sharedStyles = css`
background-color: gold;
`;
const Div = styled.div`
${sharedStyles}
`;
const Button = styled.button`
${sharedStyles}
`;
const App = () => (
<>
<Div>Hello Div</Div>
<Button>Hello Button</Button>
</>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How do you pass an image to a styled component?

I'm using styled-components in ReactJS and I'm trying to create a component that can take in the background-image as a prop. After some research, I've tried this:
import SpeechBubble1 from '../images/home_images/Speech 1.png';
...
const SpeechBubble = styled.div`
background-image: url(${props => props.background});
`;
...
<SpeechBubble background={SpeechBubble1} />
But it doesn't work. Checking in the browser element window, I can see I'm getting an Invalid property value for background-image.
What am I doing wrong?
Edit:
I also tried doing this, which hasn't worked:
<SpeechBubble style={{background: `url(${SpeechBubble1})`}} />
Make sure you are including a height for the styled component, otherwise, it won't display anything (unless it has children that define its dimensions).
Working example:
components/Container
import styled from "styled-components";
const Container = styled.div`
height: 100vh;
background-image: url(${({ background }) => background});
background-repeat: no-repeat;
background-size: cover;
`;
export default Container;
index.js
import React, { Fragment } from "react";
import { render } from "react-dom";
import reactbg from "./images/reactbg.png";
import Container from "./components/Container";
import GlobalStyles from "./components/GlobalStyles";
import Title from "./components/Title";
const App = () => (
<Fragment>
<GlobalStyles />
<Container background={reactbg}>
<Title>Hello World</Title>
</Container>
</Fragment>
);
render(<App />, document.getElementById("root"));
Index.js
import React from 'react'
import {ProfilePic} from './NavigationElements'
import profileimg from '../../images/profileimg.jpg'
const Navigation = () => {
return (
<NavigationWrapper>
<ProfilePic src={profileimg} alt="" />
</NavigationWrapper>
)
}
export default Navigation
NavigationElements.js
import styled from "styled-components";
export const NavigationWrapper = styled.div`
color: #fff;
`
export const ProfilePic = styled.img`
width: 5vh;
height: 3vh;
margin: 55px;
`
You can use inline styling:
<SpeechBubble style={{background: `url(${SpeechBubble1})`}} />

Resources