Switching between className 'active' in reactJS - javascript

I am getting the error "TypeError: Cannot read property 'isFollowing' of null" for the following code:
import React from 'react';
import styles from './Cover.css';
import withStyles from '../../../../decorators/withStyles';
import Link from '../../../../utils/Link';
import Avatar from './Avatar';
import classnames from 'classnames';
import { Button } from 'react-bootstrap';
#withStyles(styles)
class Cover extends React.Component {
toggleFollow () {
this.setState({isFollowing: !this.state.isFollowing});
}
render() {
var user = this.props.user;
var followClass = this.state.isFollowing? 'active': '';
return (
<div className="Cover">
<div className="Cover-container">
<div>
<Avatar
username= {user}
profession="Web Developer"
location="New York, New York"
status="I am here to protect my business, a bunch of kids are out to ruin me" />
<div className="Cover-submenu-container">
<div className="Cover-submenu-section">
.
</div>
<div className="Cover-submenu-section links">
<a href="#" className="Cover-submenu-link">
<i className="fa fa-twitter"></i>
</a>
<a href="#" className="Cover-submenu-link">
<i className="fa fa-facebook"></i>
</a>
</div>
<div className="Cover-submenu-section connect-menu">
<Button className={classnames('follow-btn', {followClass})} href="#" onClick={this.toggleFollow.bind(this)}>Follow</Button>
<Button className="connect-btn" href="#" onClick={this.followBtn.bind(this)}>Connect</Button>
<Button className="follow-btn" href="#" onClick={this.followBtn.bind(this)}>Follow</Button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Cover;
I could not figure out what I am doing wrong here, I am quite new to reactJS. Any idea anybody? Thanks a lot.

The first thing you need to do is to add the initial value of the isFollowing property. Because you are using ES6 syntax, it's possible to do that in the constructor. Just add this code before toggleFollow() function:
constructor(props) {
super(props);
this.state = {
isFollowing: false
}
}
The second error (based on the comments at your question) comes from not having the function followBtn() defined. Add this before render() function:
followBtn() {
alert('followBtn called'); //change it for whatever you want
}
Don't forget that clicking on both buttons (connect, follow) will now lead to the same result, because the same function will be called.

Related

Move the header with the window with react

I would like to move the whole window with its contents when I hold the mouse on the header. However, the window cannot be moved if the content is held on the click. My goal is to do something similar to a window on Windows or MacOs.
In the end the window could be moved anywhere on the screen.
Right now, when I hold the header, I see that it wants to move but the window does not.
Translated with www.DeepL.com/Translator (free version)
//header file
import React from 'react';
import ChangeClassClose from './buttonHeader/closebutton';
import ChangeClassBig from './buttonHeader/bigButton';
import ChangeClassMin from './buttonHeader/minButton';
class HeaderType extends React.Component {
render() {
return (
<>
<div className="window-header" draggable="true" onDragStart ={this.handleDragStart} onDragEnd ={this.handleDragEnd}>
<div className="TestContent">
<div className="close" id="close" title="close" onClick={ChangeClassClose}>
</div>
<div className="hide" id="min" title="diminuer" onClick={ChangeClassMin}>
</div>
<div className="open" id="big" title="agrandir" onClick={ChangeClassBig}>
</div>
<div>
</div>
</div>
<div className="test_2">
</div>
</div>
</>
)
}
}
export default HeaderType;
// app file (with window)
import React from 'react';
import HeaderType from './header';
import ColumnLeft from './column_left';
import ColumnRight from './column_right';
import { BrowserRouter, Link } from 'react-router-dom';
class App extends React.Component {
render() {
return (
<BrowserRouter>
<div className="window" id="window" onDragOver={this.handleDragOver} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave}>
<div className="window-body" id="window-body">
<HeaderType />
<div className='window_inner'>
<ColumnLeft />
<ColumnRight />
</div>
</div>
</div>
<div className="addWindowBody" id="openWindow">
<a href ='/'>
<div className="addWindow">
<i class="material-symbols-outlined">
open_in_full
</i>
</div>
</a>
</div>
<div className="addDarkMode" />
</BrowserRouter>
);
}
}
export default App;

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.

Using data from one component in another in Reactjs

I made a counting app that when you click you level and get gold, but how do use the data in another component? For example, I want to use this.state.max in another component.
Sorry, I'm quite new to React
import React, {Component} from 'react';
import '../App.css';
import darkalien from '../assets/darkgray__0000_idle_1.png';
import darkalien2 from '../assets/darkgray__0033_attack_3.png';
import darkalien3 from '../assets/darkgray__0039_fire_5.png';
var style = {
color: 'black',
fontSize: 20
};
var style2 ={
color: '#daa520',
fontSize: 20
}
export default class Home extends Component{
constructor(props) {
super(props);
this.state = {
i: 0,
j: 1,
k: 0,
max: 10,
maxf: 2,
maxi: 10
}
}
onClick(e) {
e.preventDefault();
var level = this.state.j;
this.setState({i: this.state.i + 1});
this.setState({k: this.state.k + 1});
if(this.state.i >= this.state.max){
this.setState({j: this.state.j + 1});
this.setState({i: this.state.i});
this.setState({k: this.state.k});
if(this.state.j === this.state.maxf){
this.setState({maxf: this.state.maxf + 1});
this.setState({max: this.state.max + 10});
}
this.setState({i: this.state.i = 0});
}
}
render(){
return(
<header>
<div className="container" id="maincontent" tabIndex="-1">
<div className="row">
<div className="col-lg-12">
<div className="intro-text">
<p className="name" style={style} id="demo3">Level {this.state.j}</p>
<p className="name" id="demo4" style={style}>Points: {this.state.k}</p>
<p className="name" style={style2} id="demo5">Gold: {this.state.max}</p>
<img id="picture" className="img-responsive" src={darkalien} alt="alien-img" onClick={this.onClick.bind(this)} height="150" width="150"/>
<progress id="demo2" value={this.state.i} max={this.state.max}></progress>
<h1 className="name">Click me!</h1>
<hr className="glyphicon glyphicon-star-empty"></hr>
<span className="skills">Gain Experience ★ Get Coins ★ Purchase Armor</span>
</div>
</div>
</div>
</div>
</header>
);
}
}
I want to use the this.state.max in my store component:
import React, {Component} from 'react';
import blaster from '../assets/blaster_1.png';
import blaster2 from '../assets/blaster_3.png';
import alienSuit from '../assets/predatormask__0000_idle_1.png';
import alienHair from
'../assets/alien_predator_mask_0007_hair_profile.png';
import Home from '../components/Home';
export default class Store extends Component{
render(){
return(
<section id="portfolio">
<div className="container">
<div className="row">
<div className="col-lg-12">
<h3>Armor and Weapon Store<span> **Gold:{this.state.j}** </span></h3>
</div>
</div>
<div className="row text-center">
<div className="col-md-3 col-sm-6 hero-feature">
<div className="thumbnail">
<img src={blaster} alt=""/>
<div className="caption">
<h3>Reggae Blaster</h3>
<p>
Buy Now! More Info
</p>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
}
React's architecture is specifically designed to not have cross-component dependencies. If you had a lot of those dependencies you would find yourself quickly in a 'hairball' that would make code maintenance very difficult.
However if you want to manage an App state in a controlled way I would recommend to consider using a state container (especially if your app gets more complex). You could look into Redux for example and potentially also use the server / database to store more long time data. Here is an article explaining a different categorization of states.
And of course - Here's the link to the must read me of Redux and the basic tutorial, which should help with your use case.
You could retrieve the data held in your state by creating a function in the class that returns that data. For example
export default class Home extends Component{
constructor(props) {
super(props);
this.state = {
i: 0,
j: 1,
k: 0,
max: 10,
maxf: 2,
maxi: 10
}
}
getMax(){
return this.state.max
}
//Rest of your code...
}
You would then call getMax by defining a new instance of Home with
var home = new Home
then call the getMax function wherever you need your this.state.max
var max = home.getMax()
However as the other answers have said I would recommend looking at another form of state management, my personal favorite being Redux.

How to use onClick event with <Link> in reactjs

i am trying to get the Id of a student by clicking on the . But it's giving me error like TypeError: Cannot read property 'handleClick' of undefined. What's wrong in here.?? First atleast i need to get this handleClick function to be working.
This is my react code:
class Premontessori extends React.Component{
constructor(props){
super(props);
this.state={
post:[],
id:[]
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
alert(event);
}
componentDidMount(){
let self = this;
axios.get('http://localhost:8080/list')
.then(function(data) {
//console.log(data);
self.setState({post:data.data});
self.setState({id:data.data})
});
}
render(){
console.log(this.state.id);
return(
<div className="w3-container">
<div className="w3-display-container">
<div className="w3-panel w3-border w3-yellow w3-padding-4 w3-xxlarge ">
<p >List Of Students</p>
<div className="w3-display-right w3-container">
<Link className="w3-btn-floating w3-yellow" style={{textDecoration:'none',float:'right'}} to="/createstudent">+</Link>
</div></div>
</div>
<ul className="w3-ul w3-card-4 w3-yellow"> {this.state.post.map(function(item, index) {
return (
<Link to="/displaylist" style={{textDecoration:'none'}} key={index} onClick={this.handleClick}>
<li className=" w3-hover-green w3-padding-16" >
<img src={require('./3.jpg')} className="w3-left w3-circle w3-margin-right " width="60px" height="auto" />
<span>{item.Firstname}</span><br/><br/>
</li>
</Link>
)}
)}
</ul>
</div>
);
}
}
export default Premontessori;
When you pass this.handleClick to Link, at the moment the event happens and function gets executed, the latter happens in context of instance of Link. And since Link component doesn't have handleClick prop, the operation fails.
Try to declare handleClick in a way it gets bound to current component at the time of instantiation:
handleClick = event => {
alert(event);
}
Or use Function#bind in your render function:
<Link onClick={this.handleClick.bind(this)} />
Link is already has an internal hanlder for clicking which is redirection to another Route , and it is a markup solution .
React router provides also a non-markup solution to redirect which is browserHistory.push.
Thus :
import {browserHistory} from 'react-router'
handleClick(event) {
event.preventDefault();
alert('you clicked me');
browserHistory.push('/displaylist');
}
<a style={{textDecoration:'none'}} key={index} onClick={this.handleClick}></a>
Instead of
import {Link} from 'react-router'
<Link to="/displaylist" style={{textDecoration:'none'}} key={index} onClick={this.handleClick}>

How do I properly pass function props on another component with React.Component?

I am introducing my self in es6+, I have a hard time trying to pass a function props to another component.
This is my code:
class ProductList extends React.Component {
constructor(props) {
super(props);
this.onVote = this.handleProductUpVote.bind(this);
}
handleProductUpVote(productId) {
console.log(productId +" was upvoted.")
}
render() {
const products = Data.map((product) => {
return (
<Product
key={'product-'+product.id}
id={product.id}
title={product.title}
description={product.description}
url={product.url}
votes={product.votes}
submitter_avatar_url={product.submitter_avatar_url}
product_image_url={product.product_image_url}
onVote={this.handleProductUpVote}
/>
);
});
return (
<div className="ui items">
{products}
</div>
);
}
}
I want to pass the function onVote in this component(Product)
class Product extends React.Component {
handleUpVote() {
this.props.onVote(this.props.id).bind(this) /* the error is here, I am trying
to pass the id props, and invoke the onVote prop here */
}
render() {
return (
<div className="item">
<div className="image">
<img src={this.props.product_image_url} />
</div>
<div className="middle aligned content">
<div className="description">
<a onClick={this.handleUpVote}>
<i className="large caret up icon"/>
</a>
{this.props.votes}
</div>
<div className="description">
<a href={this.props.url}>
{this.props.title}
</a>
</div>
<div className="extra">
<span> Submitted by: </span>
<img
className="ui avatar image"
src={this.props.submitter_avatar_url}
/>
</div>
</div>
</div>
);
}
}
I have no problem with other props here. I am trying to invoke the function on handleUpVote, I used bind with it, but I can't make it work. Help?
You have to use bounded handleProductUpVote method when you pass it to Product component.
As you can see in constructor, you already bound it and assigned to this.onVote property.
There are 2 solutions:
You should use onVote={this.onVote} in render method.
Change the name of property onVote in constructor to this.handleProductUpVote. And you end up with this.handleProductUpVote = this.handleProductUpVote.bind(this) and leave assignment in render method (i.e. onVote={this.handleProductUpVote})
More info at http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/
Update:
And update your Product class:
class Product extends React.Component {
constructor(props) {
super(props);
this.handleUpVote = this.handleUpVote.bind(this);
}
handleUpVote() {
this.props.onVote(this.props.id)
}
// the render method
}
Remove the bind in handleUpVote() in your Product component and just invoke it like this.props.onVote(this.props.id);

Categories