Function sent as props being called continuously - React.js - javascript

I am making a newsapp i want it to have different categories, instead of using react-router-dom for navigation what i want to do is create a state object and create a key in it named category and set current category as it's value and i have sent that key as a props to news component where i fetch news and embed that category to the fetch URL
I have made a function to set the category and its in app.js I have sent it to navbar component as props, the issue i am facing is that i can't select a category, because for some reason the onClick of the very last category is being called continuously and I know this because I console logged the category in setCategory function, can anyone tell me why this is happening
code in app.js:
import './App.css';
import React, { Component } from 'react'
import Navbar from './components/Navbar';
import News from './components/News';
export default class App extends Component {
constructor() {
super()
this.state = {
darkMode: "light",
country: "us",
category: "general",
key: "general"
}
}
setCategory = (cat)=> {
this.setState({
category: cat
})
console.log(this.state.category)
}
setCountry = (cntry)=> {
this.setState({
category: cntry
})
}
setDarkMode = () => {
if (this.state.darkMode === "light") {
this.setState({ darkMode: "dark" })
document.body.style.backgroundColor = "black"
} else {
this.setState({ darkMode: "light" })
document.body.style.backgroundColor = "white"
}
}
render() {
return (
<div>
<Navbar setCategory={this.setCategory} setCountry={this.setCountry} setDarkMode={this.setDarkMode} darkMode={this.state.darkMode} />
<News key={this.state.category} category={this.state.category} country={this.state.country} pageSize={18} darkMode={this.state.darkMode} />
</div>
)
}
}
code in Navbar component:
import React, { Component } from 'react'
export default class Navbar extends Component {
constructor(props) {
super(props)
this.setCategory = this.props.setCategory
}
render() {
return (
<div>
<nav className={`navbar navbar-expand-lg navbar-${this.props.darkMode} bg-${this.props.darkMode}`}>
<a className="navbar-brand" href="/">NewsMonkey</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item active">
<a className="nav-link" href="/">Home <span className="sr-only">(current)</span></a>
</li>
<li className="nav-item">
<a className="nav-link" href="/about">About</a>
</li>
<li className="nav-item dropdown">
<a className="nav-link dropdown-toggle" href="/" role="button" data-toggle="dropdown" aria-expanded="false">
Categories
</a>
<div className="dropdown-menu">
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("business")}>Business</p>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("science")}>Science</p>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("technology")}>Technology</p>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("entertainment")}>Entertainment</p>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("health")}>Health</p>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("sports")}>Sports</p>
<div className="dropdown-divider"></div>
<p className="dropdown-item cursor-pointer" onClick={this.setCategory("general")}>General</p>
</div>
</li>
</ul>
{/* <form className="form-inline my-2 my-lg-0">
<input className="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" />
<button className="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form> */}
<div className={`custom-control custom-switch text-${this.props.darkMode === "light" ? "dark" : "light"}`}>
<input type="checkbox" className="custom-control-input" onClick={this.props.setDarkMode} id="customSwitch1" />
<label className={`custom-control-label`} htmlFor="customSwitch1">Dark mode</label>
</div>
</div>
</nav>
</div>
)
}
}

This doesn't do what you think it does:
onClick={this.setCategory("business")}
This calls the setCategory function immediately and uses the result of that function as the onClick handler. Don't pass the result of calling a function to onClick, pass a function itself:
onClick={() => this.setCategory("business")}

Related

How can I create dynamic menu with submenu in vue 2?

I have a problem and if you can help me I would be grateful, because I am working with vue for 3 weeks.
I try to create a menu with submenu in vue 2 by two weeks and I can't succeed. the menu is created , but when I go to submenu is won't create it. the code is next:
<script>
import image from "./assets/img/logo-just-escape.png"
import axios from "axios"
export default {
data(){
const lang = localStorage.getItem('lang')
return {
imagel: image,
lang: lang,
languages:null,
menu:null,
submenu:null
}
},
async created(){
try {
var res =await axios.get(`lng`);
this.languages=res.data;
const valmenu="titles/value?language="+this.lang;
res=await axios.get(valmenu);
this.menu=res.data;
this.submenu=this.getSubMnu(this.menu);
console.log(this.submenu)
}catch(e){
console.error(e);
}
},
methods: {
handleChange(event){
localStorage.setItem('lang',event.target.value);
window.location.reload();
},
getSubMnu(value){
let temp='';
let sbmenu=[];
let variable=null;
for(temp in value){
if('2'==value[temp].subtitle){
variable=value[temp];
let temp1=value[temp].link+"\/"+this.menu[temp].id;
variable.link=temp1;
sbmenu.push(variable);
}
}
return sbmenu;
}
}
}
</script>
<template>
<div id="app" class="bg-dark">
<div>
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="/">
<img width="100" height="50" :src="imagel"/>
</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<div v-for="menuButton in this.menu" :value="menuButton.title" :key="menuButton.id">
<li class="nav-item" v-if="menuButton.subtitle ===0">
<router-link :to="menuButton.link" ><span class="nav-link">{{menuButton.title}}</span></router-link>
</li>
<li class="nav-item dropdown" v-if="menuButton.subtitle ===1" style="color: white;">
<span class="nav-link dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{menuButton.title}}</span>
<div v-for="tempor in this.submenu" class="dropdown-menu dropdown-menu-right bg-dark" :value="tempor.title" :key="tempor.id">
<span class="nav-link">{{tempor.title}}</span>
<router-link :to="tempor.link" #click.name><span class="nav-link">{{tempor.title}}</span></router-link>
</div>
</li>
</div>
<li class="nav-item">
<select class="selectpicker form-control" v-model="lang" data-width="fit" #change="handleChange($event)">
<option v-for="langu in languages" :value="langu.language_short" :key="langu.id">
{{langu.language}}
</option>
</select>
</li>
</ul>
</div>
</nav>
<div class="divmargin" >
<router-view/>
</div>
</div>
</div>
</template>
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: Cannot read property 'submenu' of undefined"
found in
---> at src/App.vue
If someone can give me some answer to this I will be very grateful.
Thank you,
Vlad.

How to use JavaScript with $ inside render() in Reactjs

I work on content editor in React admin interface.
And I'd love to install my favorite block content editor. But it's an old one and have no react version.
I know how to link .js and .css in head with ReactHelmet
But have no idea how to run following script:
<script>
$(function () {
$("#editor").brickyeditor({
ignoreHtml: true,
blocksUrl: 'data.json',
templatesUrl: 'templates.html',
onChange: function(data) {
console.log(data.html);
}
});
});
</script>
Here is initial html structure
<body>
<header>
<nav class="container navbar navbar-expand-lg navbar-light">
<a class="navbar-brand" href="index.html">BrickyEditor</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="http://brickyeditor.info/examples.html">More Examples</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/yakovlevga/brickyeditor">GitHub Repository</a>
</li>
</ul>
</div>
</nav>
</header>
<main>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="editor"></div>
</div>
</div>
</div>
</div>
</main>
</body>
Im using it like so:
import PageTitle from "../components/common/PageTitle";
import Helmet from "react-helmet";
import $ from 'jquery';
class NewsEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const {
} = this.state;
return (
<Container fluid className="main-content-container px-4">
{/* Page Header */}
<Row noGutters className="page-header py-4">
<PageTitle sm="4" title="News editor" subtitle="Drag and drop interface" className="text-sm-left" />
</Row>
<Helmet
title="Nested Title"
link={[
{"rel": "stylesheet", "href": "https://cdn.jsdelivr.net/npm/brickyeditor/dist/jquery.brickyeditor.min.css"}
]}
script={[
{"src": "https://cdn.jsdelivr.net/npm/brickyeditor/dist/jquery.brickyeditor.min.js"},
]}
/>
<header>
<script>
$(function () {
$("#editor").brickyeditor({
ignoreHtml: true,
blocksUrl: 'data.json',
templatesUrl: 'templates.html',
onChange: function(data) {
console.log(data.html);
}
});
});
</script>
<nav class="container navbar navbar-expand-lg navbar-light">
<a class="navbar-brand" href="index.html">BrickyEditor</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="http://brickyeditor.info/examples.html">More Examples</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/yakovlevga/brickyeditor">GitHub Repository</a>
</li>
</ul>
</div>
</nav>
</header>
<main>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="editor"></div>
</div>
</div>
</div>
</main>
</Container>
);
}
}
export default NewsEditor;
On this stage all I have is Failed to compile error.
UPD: Following advices I keep on getting TypeErrors
I always make re-usable components for external libraries. So in your case, it would be BrickyEditor component which could look like this:
class BrickyEditor extends React.Component {
editorRef = React.createRef();
componentDidMount() {
window.$(this.editorRef.current).brickyeditor(this.props);
}
render() {
return <div ref={this.editorRef}></div>
}
}
// in your NewsEditor component you can use it like so
<BrickyEditor
ignoreHtml={true}
blocksUrl="data.json"
templatesUrl="templates.html"
onChange={function(data) {
console.log(data.html);
}}
/>

Linking of Page on same page with nextjs

Hello everyone I need help regarding linking of pages in nextjs.
actually I know how to link but what i want is following:
I have my home page having course team contact links in navbar so when I click course then course page gets open with url "localhost:3000/course" and in that course page I have courses .
I want that by clicking on any course in course page it should get open and the url should be "localhost:3000/course/course_1".
what should I do ?
This is header component:
const Header = () => (
<div>
<nav className="navbar navbar-expand-lg navbar-dark" >
<Logo />
<button className="navbar-toggler" type="button" data-target="#navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse">
<ul className="navbar-nav">
<li>
<a href="/" className="nav-link" >Home</a>
</li>
<li>
<a href="/team" className="nav-link" >Team</a>
</li>
<li>
<a href="/courses" className="nav-link" >Course</a>
</li>
<li >
<a href="/contact" className="nav-link" >Contact</a>
</li>
</ul>
<form className="form-inline my-2 my-lg-0">
<div className="d-flex justify-content-center h-100">
<div className="searchbar">
<input className="search_input text-center" type="text" name="" placeholder="Search..." />
<i className="fas fa-search"></i>
</div>
</div>
</form>
</div>
</nav>
This is the course :
const Course = () => (
<div>
<div className="col-xs-12 col-sm-4">
<div className="card">
<a className="img-card img-part-2" href="#">
<img src="/static/course1-img.jpg" />
</a>
<div className="teacher-img">
<div className="ava">
<img alt="Admin bar avatar" src="http://ivy-school.thimpress.com/demo-3/wp-content/uploads/learn-press-profile/5/2448c53ace919662a2b977d2be3a47c5.jpg" className="avatar avatar-68 photo" height="68" width="68" />
</div>
</div>
<div className="card-content">
<p className="card-para">Charlie Brown </p>
<h4 className="card-title">
<a href="/Pyhton">
Learn Python – Interactive <br/> Python
</a>
</h4>
<div className="info-course">
<span className="icon1&-txt">
<i className="fas fa-user"></i>
3549
</span>
<span className="icon2&-txt">
<i className="fas fa-tags"></i>
education
</span>
<span className="icon3&-txt">
<i className="fas fa-star"></i>
0
</span>
</div>
</div>
</div>
</div>
You can try like this:
server.js
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('/course', (req, res) => {
return app.render(req, res, '/courses')
})
server.get('/course/:id', (req, res) => {
return app.render(req, res, '/course', { id: req.params.id })
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
course.js
import React, { Component } from 'react'
export default class extends Component {
static getInitialProps ({ query: { id } }) {
return { courseId: id }
}
render () {
return (
<div>
<h1>Course {this.props.courseId}</h1>
</div>
)
}
}
courses.js
import React, { Component } from 'react'
export default class extends Component {
render () {
return (
<div>
<a href="/course/python">
Learn Python – Interactive <br/> Python
</a>
<a href="/course/javascript">
Learn Javascript – Interactive <br/> Javascript
</a>
</div>
)
}
}

navbar from Bootstrap to reactjs

I have programmed a navbar using Bootstrap and react. In order to obtain the functionality of bootstrap must be installed and bootstrap.js jquery.js. I just want to basically use the CSS file of bootstrap and the functionality of reactjs. Does it make sense to use Bootstrap with reactjs?
I need to realize with reactjs a little help to program the navigation.
Here the source of my header. I need help to programm the navbar in reactjs without bootstrap.js and jquery.min.js
import React from "react"
export class Header extends React.Component {
render() {
return (
<nav className="navbar-kwp-header navbar-default navbar-fixed-top">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#Navbar">
<span className="sr-only">Navigation ein- / ausblenden</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<a className="navbar-brand" href="#"><img src="images/logo.jpg" alt="" /></a>
</div>
<div id="Navbar" className="navbar-collapse collapse">
<ul className="nav navbar-nav">
<li>Home</li>
<li className="dropdown"><a className="dropdown" data-toggle="dropdown" role="button" aria-expanded="false">Service <span className="caret"></span></a>
<ul className="dropdown-menu" role="menu">
<li>Downloads</li>
<li>Glossar</li>
<li>Newsletter</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
);
}
}
You can manually code a state variable to handle the toggling of the navbar:
class App extends Component {
state = {
navCollapsed: true
}
_onToggleNav = () => {
this.setState({ navCollapsed: !this.state.navCollapsed })
}
render () {
const {navCollapsed} = this.state
return (
<nav className='navbar navbar-default'>
<div className='navbar-header'>
<a className='navbar-brand' href='/'>Your Brand</a>
<button
aria-expanded='false'
className='navbar-toggle collapsed'
onClick={this._onToggleNav}
type='button'
>
<span className='sr-only'>Toggle navigation</span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
</button>
</div>
<div
className={(navCollapsed ? 'collapse' : '') + ' navbar-collapse'}
>
<ul className='nav navbar-nav navbar-right'>
<li>
<a>About</a>
</li>
</ul>
</div>
</nav>
)
}
}
You can easily use bootstrap in your react components by using react-bootstrap package.
https://react-bootstrap.github.io/
This is an example with navbar which you want to use.
import React from "react"
import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
export class Header extends React.Component {
render() {
return (
<Navbar>
<Navbar.Header>
<Navbar.Brand>
React-Bootstrap
</Navbar.Brand>
</Navbar.Header>
<Nav>
<NavItem eventKey={1} href="#">Link</NavItem>
<NavItem eventKey={2} href="#">Link</NavItem>
<NavDropdown eventKey={3} title="Dropdown" id="basic-nav-dropdown">
<MenuItem eventKey={3.1}>Action</MenuItem>
<MenuItem eventKey={3.2}>Another action</MenuItem>
<MenuItem eventKey={3.3}>Something else here</MenuItem>
<MenuItem divider />
<MenuItem eventKey={3.3}>Separated link</MenuItem>
</NavDropdown>
</Nav>
</Navbar>
);
}
}

How to highlight the selected bootstrap tab in React

I am using react for my application, and I have a bootstrap navigation bar menu has three tabs. I want to highlight the selected tab.
Here is the html code in my render() function.
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul className="nav navbar-nav navbar-left">
<li onClick={event => this.handleClick('tab1', event)} className={(this.state.activeTabClassName === "tab1") ? "active" : ""}>HOME<span className="sr-only">(current)</span></li>
<li onClick={event => this.handleClick('tab2', event)} className={(this.state.activeTabClassName === "tab2") ? "active" : ""}>RESOURCES</li>
<li onClick={event => this.handleClick('tab3', event)} className={(this.state.activeTabClassName === "tab3") ? "active" : ""}>CONTACT</li>
</ul>
</div>
I use the handleClick function to change the tabName:
handleClick(tabName, event) {
this.setState ({activeTabClassName : tabName});
//this.state.activeTabClassName = tabName;
}
I also set the initial state of activeTabClassName as 'tab1' in my constructor:
constructor() {
super();
this.state = {activeTabClassName : "tab1"};
// this.handleClick = this.handleClick.bind(this);
}
The code for the whole Nav.js component
import React from 'react';
export default class Nav extends React.Component {
constructor() {
super();
this.state = {activeTabClassName : "tab1"};
}
handleClick(tabName, event) {
this.setState ({activeTabClassName : tabName});
}
render(){
return(
<nav className="navbar navbar-default" role="navigation">
<div className="container-fluid">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<a className="navbar-brand navbar-utimg" href="https://www.xxx.xxxx" target="_blank">
<img alt="logo" src="/dist/assets/coe-logo.png"/>
</a>
</div>
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul className="nav navbar-nav navbar-left">
<li onClick={event => this.handleClick('tab1', event)} className={(this.state.activeTabClassName === "tab1") ? "active" : ""}>HOME<span className="sr-only">(current)</span></li>
<li onClick={event => this.handleClick('tab2', event)} className={(this.state.activeTabClassName === "tab2") ? "active" : ""}>RESOURCES</li>
<li onClick={event => this.handleClick('tab3', event)} className={(this.state.activeTabClassName === "tab3") ? "active" : ""}>CONTACT</li>
</ul>
<form className="navbar-form navbar-right" role="search">
<div className="form-group">
<input type="text" className="form-control" placeholder="Search"/>
</div>
<button type="submit" className="btn btn-default">Submit</button>
</form>
</div>
</div>
</nav>
)
}
}
However, it does not work well. Everytime when click the tab, it does not highlight the selected tab unless I clicked it again. Why does the onClick function not change the state right away? Is there any better solution for this problem?
Thanks!

Categories