How to give different backgrounds to the same component? - reactjs

Edited:
I am new to react, and so far couldn't find the answer to this question. I have a <Box /> component, which renders some HTML.
import React, { Component } from 'react'
class Box extends Component {
render() {
return (
<div className="box-wrapper">
<div className="different-image-for-different-copies">
</div>
<div className="box-name">
Golden Lion
</div>
</div>
)
}
}
export default Box
On one page, I have three copies of the same component. I want to be able to give unique background-image to the inner with the className different-image-for-different-copies in each of those three components without making a new component.
Component <Box /> is the child of a component <Wrapper />. What I want exactly is to be able to change the background of a certain <div> located in the child <Box /> component from the parent <Wrapper /> component. For example:
class Wrapper extends React.Component {
render() {
return (
<div>
<Box "some way to change the background of the inner div" />
</div>
)
}
}
What would be the best way to do this?

Pass you image as a props to your Box component. Then in your component, set its style like this:
<div style={{ backgroundImage: `url(${this.props.imageUrlFromProps})`}}>
</div>
That's a basic example but should help you get your image to show up.

Use a prop to pass to the component which background image it should use and set it on your component using inline style. If the set of images is limited, the rendering could instead pick a CSS class to apply.

Related

React tailwind, cannot pass tailwind css from parent to child

I am running into a simple issue that doesn't seem to have an answer on quick google search or Tailwind doc.
I am a Vuejs user but I have started learning React. I have opted to use TailwindCSS for testing my React application but I noticed there is some differences of Tailwind usage between Vuejs and React.
In Vue, I can control a child component via the parent component like so:
Parent component:
<template>
<div class="w-screen">
<ChildComponent class="w-1/2 mx-auto" />
</div>
</template>
With the child being able to centre on screen through the above parent component as should in the ChildComponent's class.
However, when I tried to do the same in React like so:
Parent component:
import Homepage from './views/Homepage';
function App() {
return (
<div className='bg-black w-screen'>
<Homepage className="w-1/2 mx-auto"/>
</div>
);
}
export default App;
Nothin happens when I placed the CSS at the Homepage child component from the parent.
I am sure there is a simple answer but I wasn't about to search the doc or use any keywords to find this problem. Anyone got a hint or confirm this is intended in React or have I done something wrong with the installation?
This is less of a Tailwind question and more of a React question. You cannot use className on the Homepage component without passing it as a prop. In your case, Homepage is not expecting any className. So while making your Homepage component you have to provide a prop called 'className' then it will work fine.
Or if you simply use a div in place of Homepage it will work normally. Have a look at this codesandbox link
You need to consider that <Homepage/> is a React component and cannot accept HTMLAttrs just like that.
this example might clear it:
const app = () => {
<div className="bg-black">
<Homepage className="bg-red" />
</div>
}
const homePage = (props) => {
<div className={props.className}>
<h1 className="bg-red">hi</h1>
</div>
}
the className that you pass to <Homepage/> is actually a props rather than Html attribure.
In Vue it's fairly straightforward but in react you need to be explicit and use className in your component
// Creating component
const Button = ({ className, children }) => {
return <button className={`${className} bg-red-500`}>{children}</button>
}
export default Button
// Using component
<Button className="text-white">MyButton</Button>
import Homepage from './views/Homepage';
function App() {
return (
<div className='bg-black w-screen'>
<Homepage className="w-1/2 mx-auto"/>
</div>
);
}
export default App;
views/Homepage
you have to receive props that are going to be passed as className
const homePage = ({className}) => {
<div className={className}>
<h1 className="bg-red">hi</h1>
</div>
}
export default homePage
then export your component

Passing down React Components dynamically through props?

I'm looking for a solution. I have a Sidebar component that needs to render a different component based on which button in the parent component is pressed. I'm unsure of the best way to approach this problem, or if its possible. Heres my React code:
Parent Component
The content prop on the Sidebar component needs to pass down different components based on which Button components are clicked (so the first Button would pass a component in the content prop, and the second would pass down a component etc).
return (
<Fragment>
<Sidebar
isOpen={this.state.menuOpen}
content={<Filters />}
/>
<PanelWrapper>
<IconContainer>
<Button />
<Button />
</IconContainer>
</PanelWrapper>
</Fragment>
)
Child Component
And here that content prop would be rendered:
class Sidebar extends Component {
render() {
return (
<Menu
customBurgerIcon={ false }
noOverlay
isOpen={this.props.isOpen}
>
{this.props.content}
</Menu>
)
}
}
Thank you
Rather than passing a component as props, I'd probably do it something like this
class Sidebar extends Component {
render() {
return (
<Menu
customBurgerIcon={ false }
noOverlay
isOpen={this.props.isOpen}
>
{switch(this.props.content) {
case("type1"): <mycomponent1 />
...
}}
</Menu>
)
}
}

how can I dynamically attach sidebar components to multiple instances of sidebar?

I'm new to React and building out a design a ran into a problem.
I have a component called SideBar. I am using this component two times, one on each side of the page.
The problem is that I would like to add different components to each instance of the SideBar component. These would be lists of various items and etc. I assumed I could next component tags but the sidebar component doesn't output.
import React, { Component } from "react";
import SideBar from "./WorkspaceComponents/SideBar";
import ScrollerBox from "./WorkspaceComponents/SideBarComponents/ScrollerBox";
class Workspace extends Component {
render() {
return (
<main className="reely-workspace">
<SideBar position="SideBarLeft">
<ScrollerBox />
</SideBar>
<SideBar position="SideBarRight" />
</main>
);
}
}
export default Workspace;
Your sidebar component should receive a children prop and render it out.
Something like this:
class Sidebar extends Component {
render() {
const {children} = this.props;
return (
<div className="sidebar">
<h1>Sidebar</h1>
{children}
</div>
)
}
}
Check out this post on react docs to understand how to compose react components: https://reactjs.org/docs/composition-vs-inheritance.html
You can make your SideBar Component a wrapper component which wraps around the content given in it.
Making SideBar Component a Wrapper Component :
class Sidebar extends Component {
render() {
return (
<div className="sidebar">
// You can add any custom element here //
{this.props.children}
</div>
)
}
}
All your element passed inside the SideBar Component will now be rendered as a part of SideBar along with what it contains.
Way to consume the wrapper component:
<SideBar>
<Content1></Content1>
<Content2></Content2>
<Content3></Content3>
</SideBar>

How to add different child components to component

I'm new to react. I'm trying to create the following structure for a component in react:
<Sidebar>
<Box>
<Title/>
<Item/>
<Item/>
</Box>
<Box>
<Title/>
<Switch/>
</Box>
</Sidebar>
I can include the Title component in the Box component and pass each title value through props. How do I include the Item component in just the first Box component and not the second?
Is the best way to pass the Item and Switch components into the Box components as props?
There are quite a few ways to do what you're asking and really it really depends on where you are going with your program.
Multiple Types of Box components (with different names)
Wrap all of you sub-components in a div, and pass that div to your Box's 'children' prop. (Slightly changes your hierarchy).
Example
<Box children={<div><Title/><Item/><Item/></div>}/>
<Box children={<div><Title/><Item/></div>}/>
Hierarchy
<Sidebar>
<Box>
<div>
<Title/>
<Item/>
<Item/>
</div>
</Box>
<Box>
<div>
<Title/>
<Switch/>
</div>
</Box>
</Sidebar>
More fancy, build your sub-components from an array or other JS object that you pass as a prop and have a function inside 'Box' that reads that array and builds your sub components.
Leverage the special children prop in order to render arbitrary children:
children is a default prop passed implicitly to every component
this children prop is automatically populated with any elements contained within the parent component
instead of using props.children you can destructure props and use ({ children(, ...otherProps) }) instead
In action:
Box.js
const Box = ({ children }) => (
<div className='box'>
{children}
</div>
)
Sidebar.js
const Sidebar = ({ children }) => (
<div className='sidebar'>
{children}
</div>
)
App.js
import React from 'react'
import Sidebar from './path/to/Sidebar'
import Box from './path/to/Box'
class App extends React.Component {
constructor() {
super()
// state or whatever
}
render() {
return (
<Sidebar>
<Box>
{/*
Anything you put in here (other components
included) will be automatically rendered
*/}
</Box>
<Box>
{/* Same here */}
</Box>
</Sidebar>
)
}
}

Element not being displayed when div is removed in react

I am quite new to react but I am trying to pass element from the Course component to my Coursebox component. I am doing this successfully but the button is being displayed since I am not passing that with this.prompt. I would like to remove the div id="course" from the HTML because I only want the course component to be displayed within the couresebox component.
This is my JSX code
class Course extends React.Component {
render() {
return (
<div className="course">
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
<button>Start exercise</button>
</div>
);
}
}
ReactDOM.render( < Course />, document.getElementById('course'));
class Coursebox extends React.Component {
render() {
return (
<div>
<Course coursename="Negotiation" progress= "20%" status="Progress"/>
<Course coursename="Frontend" progress="56%" status="Progress"/>
<Course coursename="Food" status="Progress" progress="43%"/>
</div>
);
}
}
ReactDOM.render( < Coursebox />, document.getElementById('coursebox'));
and HTML
<header id="header">
</header>
<h3 id="search"></h3>
<div id="coursebox"></div>
<div id="course"></div>
When I remove the nothing is being displayed on the page apart from the header. Since I am passing the element from Course to the Coursebox component, shouldn't I be able to remove the course div from the HTML?
If it is still needed, why is that?
Is there a way for me to only display the button when a course name is being passed?
Thanks :)
Avoid rendering the course component. Ideally there should be just one render method and all other components should be called from that component. So render on CourseBox component only.
class Course extends React.Component {
render() {
console.log("hey")
return (
<div className="course">
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
<button>Start exercise</button>
</div>
);
}
}
class Coursebox extends React.Component {
render() {
return (
<div>
<Course coursename="Negotiation" progress= "20%" status="Progress"/>
<Course coursename="Frontend" progress="56%" status="Progress"/>
<Course coursename="Food" status="Progress" progress="43%"/>
</div>
);
}
}
React.render(<Coursebox />, document.getElementById('coursebox'));
Working JS fiddle http://jsfiddle.net/kmbw9wgt/3/
1.) See this line
ReactDOM.render( < Course />, document.getElementById('course'));
You are explicitly asking react to render Course in a div which has id 'course'.
If you remove this, it will not render separately, but only from within Coursebox element.
Then you can safely remove that div.
2.) Yes, you can only show button when course name is passed. Using If condition ternary operator. Add your button in following way:
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
{ this.props.coursename ? (<button>Start exercise</button>): null}

Resources