React map adding background color special elements - javascript

I use map but I have one problem I am trying to set the background of a certain element inside the map, in my case it is "item .title" I want my element to look like this https://ibb.co/ccJzD6g as you can see in the picture background color " 100% "which I specifically set in the console for but in fact if I set" background: orange "for the sidebar_list class, then the color will be applied to all elements including the rest , https://ibb.co/ZBTX3hd and if I set the background for the titleName class it looks like this https://ibb.co/84RKBBw but I want it to look like this https://ibb.co/ccJzD6g how do i solve this problem?
Lesson.jsx
import React from 'react';
import less from "./css/lesson.module.css";
import "./css/betaLesson.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { Navbar } from "../../../Navbar/Navbar";
export class Lessons extends React.Component {
constructor(props) {
super(props);
this.state = {
indexDescription: 0,
}
}
render() {
const listLessons = this.props.lesson.map((item, index) => {
return (
<li key={index} className={less.sidebar_list} onClick={() => {
this.setState({ indexDescription: index })
}}>
<div>
<FontAwesomeIcon className={less.item_icon} icon={item.iconName} />
</div>
<div style={{background: "orange"}} className={less.titleName}>
<p>{item.title}</p>
</div>
<div className={less.titleName}>
<p>{item.titleName}</p>
</div>
</li>
);
});
return (
<>
<div className="abc">
<Navbar color="blue" bg="tomato" centerFlexNavbarContainer="flex"
navbarSearchPage="Search" navbarHomePage="Home" centerHeadlineNavbarColumn="center" />
<div className={less.wrapper}>
<div>
<div className={less.sidebar}>
<div>
<ul>
{listLessons}
</ul>
</div>
</div>
</div>
<div className={less.main_content}>
<div className={less.main_inside_content}>
<div className={less.header}>
<div>
<h2>JavaScript JSON Reference</h2>
</div>
</div>
<div className={less.info}>
<div className={less.description}>
<p>
{
this.props.lesson[this.state.indexDescription]["description"]
}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
}

First question answer: Create a new component with its own attributes separately and map/passdown the properties to the component.
Here's an example: https://codesandbox.io/s/objective-hopper-2st8g?file=/src/Lesson.js

Related

Conditionally rendering component on button click (React)

I have created a basic React project that is pulling data from a SQL server. I would like this to be able to be rendered conditionally depending on what button has been clicked.
This is my Display Users Component which is used within my AdminViewUsers component (What is actually displaying the users).
import React, { Component } from 'react';
import './customers.css';
class DisplayUsers extends React.Component{
constructor(){
super();
this.state= { users: [] }
}
componentDidMount(){
this.setState({
users: this.getItems()
})
}
getItems(){
fetch('/admin-view-users')
.then(recordset => recordset.json())
.then(results => { console.log(results.recordset); this.setState({'users': results.recordset}); });
}
render () {
console.log(this.state.users)
return (
<ul>
{this.state.users && this.state.users.map(function(user, index){
//if (user.severity === 1){
return(
<div className ="jumbotron">
<li>
Severity: {user.severity}
</li>
<li>
<p>User Name:{user.name} </p>
</li>
<li>
User Email: {user.email}
</li>
<li>
Description of Issue: {user.description}
</li>
<button>See Details</button>
</div>
)
})
}
</ul>
);
}
}
export default DisplayUsers;
This is my AdminViewUsers Component
import logo from '../codestone logo.png';
import {Link } from 'react-router-dom'
import '../bootstrap.min.css'
import '../bootstrap.min.css'
import '../App.css'
import Customers from "../Components/customers";
import DisplayUsers from "../Components/DisplayUsers";
import { ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem, DropDownButton } from 'reactstrap';
function Home() {
return (
<div>
<Header/>
<SeveritySelector/>
<DisplayUsers/>
</div>
);
}
function Header(){
return (
<div class="jumbotron">
<div className = "User-Menu">
<Link>User details </Link>
</div>
<img className='profile-image' alt='icon' src={logo} width="340" height="60"/>
<Navigation/>
</div>
)
}
function Navigation (){
return(
<div>
<br/>
<div class="btn-group">
<Link to= '/home'><button type="button" class="btn btn-light">Home</button></Link>
<Link to= '/admin-view-users'><button type="button" class="btn btn-light">View Users(Admin)</button></Link>
</div>
</div>
)
}
function SeveritySelector (){
return(
<div className = "Severity-Toolbar">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button type="button" class="btn btn-secondary">Severity High</button>
<button type="button" class="btn btn-secondary">Severity Medium</button>
<button type="button" class="btn btn-secondary">Completed</button>
<button type="button" class="btn btn-secondary">View All</button>
</div>
</div>
</div>
)
}
export default Home;
Essentially I would like to use the function Severity Selector to be the decider of how the statement is displayed.E.g If the high severity button is selected then it will display all with a high severity (1) if medium selected all with medium severity (2) and completed to have a severity of 3. Finally a button to display all.
What in your opinion is the best way to do this? I understand I could use multiple statements within my "server.js" and load different queries and have them connected to different pages.
But is there a way that I could just use a if statement or something similar to determine what button is selected to avoid multiple transactions with the server? You can see a brief attempt I had within the display users with an if statement which worked but just was not dependent on the buttons.
Conditional render can be achieved using various techniques, the most used is the bracket style variant. It can be used in the following way:
function Header(){
const showFirst = true;
return (
<div class="jumbotron">
{showFirst && <MyFirstComponent />}
{!showFirst && <MySecondComponent />}
</div>
)
}
This will render the <MyFirstComponent /> if showFirst is true and will show <MySecondComponent /> if it is false.

React state change not causing re-render

I am trying to toggle the visibility of a div when clicking a seperate div. The problem is it sets the div invisible on the first click and only if it is visible to begin with. After that it just stays invisible and will not update. The state is still being toggled in the console however.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(){
super()
this.state = {
vis: '0'
}
}
toghide=()=>{
console.log("toggle login", this.state.vis)
if(this.state.vis === "hidden"){
console.log('showing')
this.setState((state, props)=>({vis:'0'}))
} else {
console.log('hiding')
this.setState((state, props)=>({vis:'hidden'}))
}
}
render() {
const styles = {
visibility: this.state.vis
}
return (
<div className="App">
<div className="salebar"><a className="salebar sale"
href="login">Click here!</a></div>
<div className="navbar">
<div className="nav"><div className="nnav">JMZ</div></div>
<div className="nav2"><div className="nnav2">PRODUCTS</div></div>
<div className="loginContainer"><div className="login" onClick={this.toghide}>LOGIN/SIGN UP</div></div>
</div>
<div className="login-container">
<div className="lognester">
<div style={styles} className="login-tab">
<input className="user" type="text" placeholder="Username"/>
<input className="password" type="password" placeholder="Password"/>
<button className="user">Login</button>
Sign in or <a className="register-link" href="register">register</a> a new account.
</div>
</div>
</div>
<div className="intro-pics"></div>
<div className="content"></div>
<audio preload loop controls autoPlay className="audio">
<source src="https://memefly.me/i/toValhalla.mp3"/>
Your browser does not support the audio element.
</audio>
</div>
);
}
}
export default App;
Try this:
class App extends Component {
constructor() {
super();
this.state = {
vis: true
};
}
toghide = () => {
this.setState({ vis: !this.state.vis });
};
render() {
return (
<div className="App">
<div className="salebar">
<a className="salebar sale" href="login">
Click here
</a>
</div>
<div className="navbar">
<div className="nav">
<div className="nnav">JMZ</div>
</div>
<div className="nav2">
<div className="nnav2">PRODUCTS</div>
</div>
<div className="loginContainer">
<div className="login" onClick={this.toghide}>
LOGIN/SIGN UP
</div>
</div>
</div>
<div className="login-container">
<div className="lognester">
{this.state.vis ? (
<div className="login-tab">
<input className="user" type="text" placeholder="Username" />
<input
className="password"
type="password"
placeholder="Password"
/>
<button className="user">Login</button>
Sign in or{' '}
<a className="register-link" href="register">
register
</a>{' '}
a new account.
</div>
) : (
''
)}
</div>
</div>
<div className="intro-pics" />
<div className="content" />
</div>
);
}
}
export default App;
This is the demo: https://codesandbox.io/s/72zzk2xr70
Two things are wrong with your code
It should be visibility:visible not visibility: 0. So change that.
Never ever ever ever... set state in your render function, really really bad practice.
1 ) You can declare your togHide method above render such as
toghide = () => {
//your code
}
render(){...}
2) You may handle visibility condition better if you just use true/false boolean logic on your vis state. This can be as :
constructor(){
super()
this.state = {
vis: true
}
}
toghide = () => {
if(this.state.vis){
this.setState({
vis : false
})}
else{
this.setState({
vis : true
})}
3) In toghide method, you can use the code for setState I've used above. You don't have to pass props if you don't use any, and don't need to use return in setState.

Update component with data from parent in React

In my react app I have this child component that inherits data from its parent. However, it does not update the page with new data from the child component when a relevant anchor link is clicked.
Here's my build - https://suite-search-lk.surge.sh/result/369523
From the link above if you click on a suggested card h1 element it just updates the URL with the id but does not update the page with the relevant card data from that id.
Any idea how I can fix this? Do I have to force the component to re-update?
Parent component (Card Wrapper)
class CardWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
stories: []
};
}
componentDidMount() {
axios
.get(API)
// .then(response => console.log(response))
// get our stories array, check it and then change state to contain our stories
.then(data => {
let stories;
if (data.data.stories && data.data.stories) {
if (Array.isArray(data.data.stories)) {
stories = data.data.stories;
} else {
stories = [data.data.stories];
}
} else {
stories = [];
}
this.setState({
stories: stories
});
});
}
render() {
return (
<CardWrapperDiv>
<div className="headingWrapper">
<div className="heading"> Suggested for you</div>
</div>
<Cards>
{this.state.stories.map(story => {
return (
<Card
title={story.content.title}
img={story.content.img}
description={story.content.description}
deadline={story.content.deadline_date}
tags={story.content.tags}
key={story.id}
id={story.id}
/>
);
})}
</Cards>
</CardWrapperDiv>
);
}
}
export default CardWrapper;
Child component
class Card extends React.Component {
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
Sorry it seems I have figured this out using the following post - Can you force a React component to rerender without calling setState?
Although I'm not exactly sure if it's the best way to go about it.
Essentially I used an OnClick listener to run a function and forces a re-render of the entire component.
Hope this can help someone else :)
class Card extends React.Component {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`} onClick={this.handleButtonClick}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
U have to use ur child component as a pure component. PureComponent Update when ur props change.
class Card extends React.PureComponent {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
.....
.....
</CardDiv>
);
}
}
export default Card;

Changing multiple props const to class

I want to convert functional component in React to class based component, because I want to make use of state property.
Currently I have this component which has 2 props.
const VideoListItem = ({video, onVideoSelect}) => {
const imageUrl=video.snippet.thumbnails.default.url;
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title}</div>
</div>
</div>
</li>
)
}
I tried to convert it to class and ended up with this:
class VideoListItem extends React.Component {
render() {
const {video} = this.props.video
const imageUrl=video.snippet.thumbnails.default.url;
const{onVideoSelect} =this.props.onVideoSelect
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title}</div>
</div>
</div>
</li>
)
}
}
However It does not work, I get errors. I guess it has something to do with 2 props being in the component. Anyone has idea how can I change the first code to be a class component?
Your destructuring is a bit off:
const { video } = this.props.video;
const{ onVideoSelect } = this.props.onVideoSelect;
should be something like:
const { video } = this.props;
const{ onVideoSelect } = this.props;
and you can combine these if you want:
const { video, onVideoSelect } = this.props;

What is the best way to make certain text in a paragraph prop bold in react?

I am dropping paragraphs into a reusable component, but certain words in each different instance of that component are bold. What is the best way to be able to bold those certain unique words ?
class Recommendations extends Component{
constructor(){
super();
}
render(){
let { mainHeader, secondaryHeader, paragraph1, paragraph2, photoClass } = this.props;
return (
<div className="mainRecommendationContainer">
<div class="recommendationContainer">
<div className="headerContainer">
<h1>{mainHeader}</h1>
<h2>{secondaryHeader}</h2>
</div>
<p>{paragraph1}</p>
<p>{paragraph2}</p>
</div>
<div className={photoClass}>
</div>
<Link to={`/`} activeClassName="active"> <div className="homeButton"></div></Link>
<Link to={'/'} activeClassName="active"><div className="back"></div></Link>
</div>
)
}
}
export default Recommendations
here is the prop and i tried to do string interpolation to make it bold, but the actual <b>example</b> were displayed
<Recommendations
mainHeader={'Almost perfect!'.toUpperCase()}
secondaryHeader={'You’ve Got Very Little Damage!'.toUpperCase()}
paragraph1={`Your hair is pretty healthy, but daily ${'example'.bold()} at the ends of your hair can make sure itfeels awesome!`}
/>
You can use dangerouslySetInnerHTML, here's the demo:
https://codesandbox.io/s/q90nz5l184
class Recommendations extends React.Component {
constructor() {
super();
}
render() {
let { mainHeader, secondaryHeader, paragraph1, paragraph2, photoClass } = this.props;
return (
<div className="mainRecommendationContainer">
<div class="recommendationContainer">
<div className="headerContainer">
<h1>{mainHeader}</h1>
<h2>{secondaryHeader}</h2>
</div>
<p dangerouslySetInnerHTML={{__html: paragraph1}} />
<p>{paragraph2}</p>
</div>
<div className={photoClass}>
</div>
</div>
)
}
}

Categories