react - add icons to header inside component - javascript

i am currently trying to solve a react problem.
i want to be able to add icons to a container called SalesChannels.
here is the code to the salesChannels page: (JSX)
import React, { Component } from 'react';
import PageContent from 'components/PageContent';
import IBox from 'components/IBox';
export default class SalesChannelsPage extends Component {
constructor(props) {
super(props);
this.state = {
rows: []
}
}
render() {
return (
<PageContent header="Salgskanaler">
<IBox title="Salgskanaler">
</IBox>
</PageContent>
);
}
}
As you can see, i have added a component called IBox. this should be reusable
it looks like this:
import React, {Component} from 'react';
import IBoxTools from './IBoxTools'
export default class IBox extends Component {
render() {
return(
<div className="ibox">
<div className="ibox-title">
{this.props.title}
//this is where the icon should be rendered in the dom
</div>
<div className="ibox-content">
{this.props.children}
</div>
</div>
);
}
}
i have also created another component called IBoxTools - this contains the actual icon / "i" tag:
import React, {Component} from 'react';
export default class IBoxTools extends Component {
render() {
let icon;
if(this.props.icon) {
icon = (
<a title={this.props.title}>
<i onClick={() => this.iconClicked()} className={`pull-right ${this.props.icon}`}></i>
</a>
);
}
return icon;
}
iconClicked() {
console.log('icon clicked')
}
}
So what i am trying to do is add multible icons to the SalesChannels page, inside the IBox tag, without making the IBox component dependent on it.
I hope you can help. Thanks!

You can pass components or arrays of components in props just like children
<IBox
title="Salgskanaler"
icons={[
<IBoxTools key="icon1" icon="foo" />,
<IBoxTools key="icon2" icon="bar" />
]}
>
{/* normal children here */}
</IBox>
Then inside IBox you write { this.props.icons } which will render the icons (or whatever else) if you pass it in.. otherwise will display nothing if the prop is undefined.

You could just use a condition if you don't want to display the icon every time. If I understand what you're attempting to do ...
import React, {Component} from 'react';
import IBoxTools from './IBoxTools'
export default class IBox extends Component {
render() {
return(
<div className="ibox">
<div className="ibox-title">
{this.props.title}
//this is where the icon should be rendered in the dom
{(condition) ? <IBoxTools /> : ""}
</div>
<div className="ibox-content">
{this.props.children}
</div>
</div>
);
}
}
Or if you need to do it multiple times, like you said, then I would use underscore.js or something like it that has a map function.
{_.map(icons, function(icon) {
return (
<IBoxTools />
)
})}
Or some combination of the two.

Related

Class Component --> Expecting string/class/function got object --> component pass to other component -->react

// -----App.js
import logo from './logo.svg';
import './App.css';
import Navbar from './components/Navbar';
import News from './components/News';
import NewsItem from './components/NewsItem';
function App() {
return (
<div>
<Navbar />
<News />
</div>
);
}
export default App;
// ----- News.js
import React, { Component } from 'react'
import NewsItem from './NewsItem';
export class News extends Component {
render() {
return (
<div>
<NewsItem />
</div>
)
}
}
export default News
//----- NewsItem.js
import React, { Component } from 'react'
export class NewsItem extends Component {
render() {
return (
<div>
NewItem component
</div>
)
}
}
export default NewsItem
I am new to react and trying to learn the basics.I tried to resolve the issue but couldn't find out the actual cause. I tried to search same issue over the internet but can't find any. All though the error msg is same but situation is different.
As you can see the NewsItem.js component is passed to News.js. Is it ok to pass a class component to another class component as a return type?
I'm getting the error as shown in img.
enter image description here
Try to remove export before defining the class
class News extends Component ...
class NewsItem extends Component ...
You are already default exporting it at the bottom

How to switch between CSS styles of React components when changing routes?

I have a React app which now has two routes (the main landing page and career page).
I made one reusable JumbotronResponsive component and i am rendering that single component as child under JumbotronLanding component (for landing page) and as child under JumbotronCareer component (for career page).
Like this
import React, { PureComponent } from 'react'
import { ResponsiveJumbotron } from '../../HOC';
import './jumbotronCareer.css';
export default class JumbotronCareer extends PureComponent {
render() {
return (
<>
<ResponsiveJumbotron/>
</>
)
}
}
and this
import React, { PureComponent } from 'react';
import { ResponsiveJumbotron } from '../../HOC';
import './jumbotronLanding.css';
export default class JumbotronLanding extends PureComponent {
render() {
return (
<>
<ResponsiveJumbotron/>
</>
)
}
}
As you can see those parent components have styles in which i want to style some ResponsiveJumbotron's parts.
For example i wish font-size of jumbotron in landing page be 70px and in career page be 45px.
But when i switch between routes those styles are like in one CSS file.
The question is 'how to separate them from each other?'.
You can add a className property and in your ResponsiveJumbotron use it like
const ResponsiveJumbotron = props => <div className={props.className} />;
[...]
export default class JumbotronLanding extends PureComponent {
render() {
return (
<>
<ResponsiveJumbotron className="landing-page" />
</>
)
}
}
and you can use that css class in your stylesheet

I have two components. I want to call 1st component into the second component. How can I do it?

I have two components. I want to call 2nd component into the first component component
//first component
import React, { Component } from "react";
class Admin extends Component {
render() {
return (
<div>
<button>admin login</button>
</div>
);
}
}
export default Admin;
...
//2nd component
import React, { Component } from "react";
import Admin from "./components/Admin";
class Main extends Component {
render() {
return (
<div>
<p>main page</p>
<Admin />
</div>
);
}
}
export default Main;
if you want the second component in the first component just import it and place it in the div
import React, { Component } from "react";
import Main from "./components/Main"
class Admin extends Component {
render() {
return (
<div>
<button>admin login</button>
<Main/>
</div>
);
}
}
export default Admin;
But doing that you will have to take Admin out of the Main component:
import React, { Component } from "react";
class Main extends Component {
render() {
return (
<div>
<p>main page</p>
</div>
);
}
}
export default Main;
Not sure if I am understanding this correctly, but since you've loaded the 1st Component () into the 2nd component already, I would expect that trying to call the second one into the first will cause an error due to an infinite import issue.
If you only want the second component in the first, but not first in the second, then the answer by Brad Ball should work.
Taking a look at the code you're presenting to us, we can see you're invoking Admin as a Child Component of Main.
#Brad Ball gave you the inverse, invoking Main as a Child Component of Admin.
If you want to compose them one needs to be the parent, the other the child.
If you want them to be siblings you need a third component to be the parent of both.
Can you explain better what you want to do?

ReactJS is not rendering children

this is my simple home.js code. None relevant code has been removed.
import Banner from '../components/Banner'
export default function Home() {
return (
<Hero>
<Banner title="luxurious rooms" subtitle="delux rooms starting at $299">
<Link to="/rooms" className="btn-primary">
Our rooms
</Link>
</Banner>
</Hero>
and this my banner.js
import React from 'react'
export default function Banner({childern,title,subtitle}) {
return (
<div className="banner">
<h1>{title}</h1>
<div />>
<p>{subtitle}</p>
{childern}
</div>
)
}
I don't understand why it is not rendering.
In the bedg I contd see <banner>. tag inside of hero.
How can I solve this issue?
Ok, I created a pen for this, but it's not saving so I'll add the code here. It looks like you are taking a difficult approach for a relatively easy concept. When you pass props to a component, you access them within that component using this.props.nameOfProp. You don't need to pass link as a child, just add Link inside the child component, and pass the info you need for the Link as props.
EDIT: Here's a working example https://codesandbox.io/embed/elegant-fast-m52bt
import React from "react";
import ReactDOM from "react-dom";
import Banner from "./Banner";
import { BrowserRouter as Router } from "react-router-dom";
class App extends React.Component {
render() {
return (
<div>
<Banner
title={"luxurious rooms"}
subtitle={"delux rooms starting at $299"}
path={"/rooms"}
classList={"btn-primary"}
/>
</div>
);
}
}
ReactDOM.render(
<Router>
<App />
</Router>,
document.querySelector("#app")
);
Then your banner should look something like this:
import React from "react";
import { Link } from "react-router-dom";
class Banner extends React.Component {
render() {
return (
<div className="banner">
<h1>{this.props.title}</h1>
<p>{this.props.subtitle}</p>
<Link
to={this.props.path}
className={this.props.classList}
>
Link Text (could also be a prop)
</Link>
</div>
);
}
}
export default Banner;

How to get refs from another component in React JS

The code in main App component is as follows :
class App extends Component {
componentDidMount(){
console.log(this.ref);
debugger;
}
render() {
return (
<div>
<Header/>
{this.props.children}
<Footer/>
</div>
);
}
}
And one of the components which renders with {this.props.children} is HomePage, where are sections with refs.
The code of a HomePage is as follows :
render(){
return (
<div className="homeMain">
<section ref="info"> <Info/> </section>
<section ref="contact"> <Contact /> </section>
</div>
);
}
How can I get those refs inside App component to be able to pass them as props to header?
I'm trying to do it inside componentDidMount in App component, but console.log(this.refs) is empty.
Any advice?
EDIT
The whole App component :
import React, {Component} from 'react';
import Footer from './common/footer';
import Header from './common/header';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as actions from './components/homepage/login/authActions';
class App extends Component {
componentDidMount(){
console.log(this.props.children.refs);
debugger;
}
render() {
return (
<div>
<Header route={this.props.location.pathname}
language={this.props.language.labels}
authenticated={this.props.authenticated}
signoutAction={this.props.actions}
offsets={this.props.offsets}
/>
{React.cloneElement(this.props.children, {
currentLanguage: this.props.language.labels,
authenticated: this.props.authenticated
})}
<div className="clearfix"/>
<Footer currentLanguage={this.props.language.labels}/>
</div>
);
}
}
function mapStateToProps(state, ownProps) {
return {
language: state.language,
authenticated: state.auth.authenticated,
offsets: state.offsets
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actions, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
The React's main idea is passing props downward from parent to children (even to deeper levels of children - grandchildren I mean)
Therefore, when we want the parent to do something which is triggered from (or belongs to) the children, we can create a callback function in the parent, then pass it down to children as props
For your preference, this is a demonstration on how to pass callback functions downward through many levels of children and how to trigger them:
Force React container to refresh data
Re-initializing class on redirect
In your case, you can access refs from children components as follows: (using string for ref - as you stated)
Parent Component:
import React, { Component } from 'react';
// import Child component here
export default class Parent extends Component {
constructor(props){
super(props);
// ...
this.getRefsFromChild = this.getRefsFromChild.bind(this);
}
getRefsFromChild(childRefs) {
// you can get your requested value here, you can either use state/props/ or whatever you like based on your need case by case
this.setState({
myRequestedRefs: childRefs
});
console.log(this.state.myRequestedRefs); // this should have *info*, *contact* as keys
}
render() {
return (
<Child passRefUpward={this.getRefsFromChild} />
)
}
}
Child Component:
import React, { Component } from 'react';
export default class Child extends Component {
constructor(props){
super(props);
// ...
}
componentDidMount() {
// pass the requested ref here
this.props.passRefUpward(this.refs);
}
render() {
return (
<div className="homeMain">
<section ref="info"> <Info/> </section>
<section ref="contact"> <Contact /> </section>
</div>
)
}
}
ref is property of each this.props.children hence you can access ref of child component in parent via ref property on this.props.children
Make sure you access ref after componentDidMount
Edit :
Try below set of code if this works :
var myChild= React.Children.only(this.props.children);
var clone = React.cloneElement(myChild, { ref: "myRef" });

Categories