Being new to both Meteor and React, I'm going about this is a non-reactive way and I know it's incorrect, but I'm having a hard time figuring out what the proper way to do this might be.
1) logIn and logOut variables should be a function, I think, but I'm not clear on how to put a function in a render.
2) Meteor.logout(document.location.reload());, seems incorrect.
I feel like I could merge these two concepts into one.
export default class Header extends React.Component {
render() {
$(".button-collapse").sideNav();
var navStyle = {
backgroundColor: "#263238",
paddingLeft: "10px"
};
var logIn = {
display: (Meteor.userId() ? "none" : "block")
};
var logOut = {
display: (Meteor.userId() ? "block" : "none")
};
return (
<nav style={navStyle}>
<div>
ShortShape
<i className="material-icons">menu</i>
<ul className="right hide-on-med-and-down">
<li>Home</li>
<li style={logOut}>Logout</li>
<li style={logIn}>Register</li>
<li style={logIn}>Login</li>
<li>Stories</li>
</ul>
<ul className="side-nav" id="mobile-demo">
<li>Home</li>
<li style={logOut}>Logout</li>
<li style={logIn}>Register</li>
<li style={logIn}>Login</li>
<li>Stories</li>
</ul>
</div>
</nav>
);
}
}
In order to make your component renders reactively, you need to wrap it in a reactive container. There are quite a lot reactive container out there, but I usually use createContainer which is the official container from Meteor team
import { createContainer } from 'meteor/react-meteor-data';
class Header extends React.Component {
logout() {
Meteor.logout(() => {
window.location.reload();
});
}
render() {
const user = this.props.user;
$(".button-collapse").sideNav();
var navStyle = {
backgroundColor: "#263238",
paddingLeft: "10px"
};
var logIn = {
display: (user ? "none" : "block")
};
var logOut = {
display: (user ? "block" : "none")
};
return (
<nav style={navStyle}>
<div>
ShortShape
<i className="material-icons">menu</i>
<ul className="right hide-on-med-and-down">
<li>Home</li>
<li style={logOut}>
<a onClick={this.logout}>Logout</a>
</li>
<li style={logIn}>Register</li>
<li style={logIn}>Login</li>
<li>Stories</li>
</ul>
<ul className="side-nav" id="mobile-demo">
<li>Home</li>
<li style={logOut}>
<a onClick={this.logout}>Logout</a>
</li>
<li style={logIn}>Register</li>
<li style={logIn}>Login</li>
<li>Stories</li>
</ul>
</div>
</nav>
);
}
}
export default createContainer(() => {
// this function will run reactively
return {
user: Meteor.user(),
};
}, Header);
Related
const pages = ["main", "about", "contact"];
const pagesList = pages.map((page) => <li>{page}</li>);
Result:
<ul>
<li>Main</li>
<li>About</li>
<li>Contact</li>
</ul>
i want to set "a" tag to "Main and About" "li". How can i do that? Thanks for your help
If you want to use map, you can try this
const pages = ["main", "about", "contact"];
let currentIndex = 0;
const pagesList = pages.map((page) =>
{
currentIndex === pages.length - 1 ? <li>{page}</li> : <li a>{page}</li>
currentIndex++;
});
Thanks to everyone who helped me. I solved my problem
i was trying to this:
<ul>
<li>
<a href='/test'>Home</a>
</li>
<li>
<a href='/test'>test1</a>
</li>
<li>
<a href='/test'>test2</a>
</li>
<li>
<a href='/test'>test3</a>
</li>
<li>test4</li>
</ul>
every li elements has "a" element but last li not have "a" element i tried to do this.
my pageHeader.js component its like this
import React from "react";
import { Link } from "react-router-dom";
export const PageHeader = (props) => {
const pages = props.pages;
const pagesList = pages.map((page) => (
<>
{page == pages[pages.length - 1] ? (
<li>{page}</li>
) : (
<li>
<Link to='test'>{page}</Link>
</li>
)}
</>
));
return (
<>
<div className='pageHeader'>
<ul>{pagesList}</ul>
</div>
</>
);
};
I find the last data with javascript length expression;
I added element "a" with "if" "else" statements.
then i called this component in my work place like this:
<PageHeader pages={["Home", "test1", "test2", "test3", "test4"]} />
you can solve this by CSS only
ul.parent>*:last-child {
color: red;
}
<ul class="parent">
<li>Main</li>
<li>About</li>
<li>Contact</li>
</ul>
I am trying to add 'active' class name to clicked navbar item dynamically and remove the 'active' class name from class respectively. I am using bootstrap so 'active' class name change the color of the li item.
class NavBar extends React.Component {
render() {
return (
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Blog - App</a>
</div>
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Chat</li>
<li>About</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
I am new with React, do i need to handle onClick with a function? I will appreciate any idea or code suggestions.
In react you can do it like this:
By passing in a prop which determines the toggle of className.
const NavBar = props => {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={props.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
export default NavBar
By State
But then in this case wouldn't be appropriate because nothing is going to click it.
import {useState} from 'react';
const NavBar = () => {
const [active, setActive] = useState('');
clickToChange () {
setActive(true);
}
render() {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={state.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
In your particular use case I'd probably suggest instead detecting the route
See example here:
React Router v4 - How to get current route?
yes, you could use onClick handler, but then again you will have to rehydrate it from the window.location;
class NavBar extends React.Component {
render() {
state = { active : null }
componentDidMount(){
/** you might as well check if location.pathname includes what you are looking
for before just setting it to state, assuming that there wont be anything
extra; skipping that for simplicity*/
this.setState(window.location.pathname);
}
handleClick = (activeLink) => {
this.setState(activeLink);
}
return (
<nav className="navbar navbar-inverse">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">Blog - App</a>
</div>
<ul className="nav navbar-nav">
<li onClick={()=>this.handleClick('/main')} className={`{this.state.active==='/main'? 'active':''}`}>Home</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
A more graceful implementation would be using a client side routing library like react-router which gives you Link components like NavLink which attaches active classnames automatically.
The on onclick function which should call the function which is HTML inside Java-script (JSX). Does not seems to work??
Does onClick only works on a button or does it also work on the lists too?
class Top extends React.Component{
constructor(){
super();
this.searchjsx = this.searchjsx.bind(this);
}
searchjsx = () =>{
return(
<div id='searchdiv'>
<form id='searchform'>
<input type="text" id="input" name="search"></input>
</form>
</div>
);
}
render(){
return(
<div>
<div id="navbar">
<ul id="nav">
<li><a className="a" href='https://www.google.com/'>Home</a></li>
<li><a className="b" href='https://www.google.com/'>Profile</a></li>
<li><a className="c" href='https://www.google.com/'>Pricing</a></li>
<li onClick={this.searchjsx} id='sch'>Search..</li>
</ul>
</div>
<div>
</div>
</div>
);
}
}
The below worked for me:
import React from "react";
export default class Top extends React.Component {
state = {
showForm: false
};
searchjsx = () => {
console.log("Toggled showForm");
this.setState({ showForm: !this.state.showForm });
};
render() {
return (
<div>
<div id="navbar">
<ul id="nav">
<li>
<a className="a" href="https://www.google.com/">
Home
</a>
</li>
<li>
<a className="b" href="https://www.google.com/">
Profile
</a>
</li>
<li>
<a className="c" href="https://www.google.com/">
Pricing
</a>
</li>
<li onClick={this.searchjsx} id="sch">
Search..
</li>
{this.state.showForm ? (
<div id="searchdiv">
<form id="searchform">
<input type="text" id="input" name="search"></input>
</form>
</div>
) : (
""
)}
</ul>
</div>
<div></div>
</div>
);
}
}
Notes:
onclick should work on any element
You were trying to insert the form inside the onClick attribute. Instead, you should change the state of the component when li is clicked and based on the state show or hide the form
You don't seem to need a constructor in this example
import React from "react";
export default class Top extends React.Component{
state = {
show:false
}
showInput() {
return(
<div id='searchdiv'>
<form id='searchform'>
<input type="text" id="input" name="search"></input>
</form>
</div>
);
}
handleShow() {
this.setState({
show: !this.state.show
})
}
render(){
return(
<div>
<div id="navbar">
<ul id="nav">
<li><a className="a" href='https://www.google.com/'>Home</a></li>
<li><a className="b" href='https://www.google.com/'>Profile</a></li>
<li><a className="c" href='https://www.google.com/'>Pricing</a></li>
<li onClick={e => this.handleShow(e)} id='sch'>Search..</li>
{
this.state.show ? this.showInput() : null
}
</ul>
</div>
</div>
);
}
}
You have to maintain a state variable that can control when to display a component. In this case, show.
I am trying to paginate JSON data that I am using with JSON server in React. I am currently using splice to break the data up into pages with 10 items per page. To get the data from each splice I have an unordered list where the list items are assigned the data. I actually want to just have pages and a next button rather than have each page listed at the top of the page, but I cant seem to wrap my head around it. I would like to use _page _limit. Any help would be appreciated. Here is the code.
import React, { Component } from 'react';
// added axios to assist with API calls.
import axios from 'axios';
import './App.css';
import Card from './Card.js';
import SearchBar from "./SearchBar.js"
import star from './images/star.svg';
import wars from './images/wars.svg';
class App extends Component {
constructor(props) {
super(props);
this.state = {
people: []
}
}
componentDidMount() {
this.getPeopleData();
}
getPeopleData(search) {
axios.get('http://localhost:3008/people?_start=0&_end=9&q=' + search).then((response) => {
this.setState ({
people: response.data
});
});
}
//1. Using axios and decided to use the slice method rather than the _page _limit from https://github.com/typicode/json-server#slice
limitPerPage (begin, end) {
axios(`http://localhost:3008/people?_start=${begin}&_end=${end}`).then((response) => {
this.setState ({
people: response.data
});
});
}
render() {
return (
<div className='content'>
<div className='logo'>
<img src={star} alt="star-logo" />
<span className='interview-text'>The Interview</span>
<img src={wars} alt="wars-logo" />
</div>
<h2>Cards</h2>
{/* Decided to display the card pages as a list. Each page holds 10 cards */}
<ul className="card-pagination">
<li>
<a onClick={() => this.limitPerPage(0, 9)}>Page 1</a>
</li>
<li>
<a onClick={() => this.limitPerPage(10, 19)}>Page 2</a>
</li>
<li>
<a onClick={() => this.limitPerPage(20, 29)}>Page 3</a>
</li>
<li>
<a onClick={() => this.limitPerPage(30, 39)}>Page 4</a>
</li>
<li>
<a onClick={() => this.limitPerPage(40, 49)}>Page 5</a>
</li>
<li>
<a onClick={() => this.limitPerPage(50, 59)}>Page 6</a>
</li>
<li>
<a onClick={() => this.limitPerPage(60, 69)}>Page 7</a>
</li>
<li>
<a onClick={() => this.limitPerPage(70, 79)}>Page 8</a>
</li>
<li>
<a onClick={() => this.limitPerPage(80, 89)}>Page 9</a>
</li>
</ul>
{this.state.people.map((person) => {
return <Card
key={person.id}
id={person.id}
name={person.name}
imageURL={('http://localhost:3008/' + person.image)}
birthday={person.birth_year}
planetList={this.state.planets}
homeWorld={person.homeworld}
/>
})}
</div>
);
}
}
export default App;
constructor(props) {
super(props);
this.state = {
people: [],
_page_limit: 10,
currentPage: 0
}
}
...
limitPerPage (begin, end, increase) {
axios(`http://localhost:3008/people?_start=${begin}&_end=${end}`).then((response) => {
this.setState ({
people: response.data,
currentPage: this.state.currentPage + increase
});
});
}
_renderLinks() {
var cp = this.state.currentPage
if (cp == 0) {
// show only "Page 1" and "Next"
return (
<ul className="card-pagination">
<li>Page 1</li>
<li><a onClick={() => this.limitPerPage(10, 20, 1)}>Next</a></li>
</ul>
)
} else if (cp < this.state._page_limit - 1) {
// show "Back", "Page X" and "Next"
return (
<ul className="card-pagination">
<li><a onClick={() => this.limitPerPage((cp-1) * 10, cp * 10), -1}>Back</a></li>
<li>Page {(cp + 1}</li>
<li><a onClick={() => this.limitPerPage((cp+1) * 10, (cp+2) * 10, 1}>Next</a></li>
</ul>
)
} else {
// show "Back", "Page X" and "Next"
return (
<ul className="card-pagination">
<li><a onClick={() => this.limitPerPage((cp-1) * 10, cp * 10, -1)}>Back</a></li>
<li>Page {(cp-1)}</li>
</ul>
)
}
}
render() {
var _page_limit = 10
return (
<div className='content'>
<div className='logo'>
<img src={star} alt="star-logo" />
<span className='interview-text'>The Interview</span>
<img src={wars} alt="wars-logo" />
</div>
<h2>Cards</h2>
{this._renderLinks()}
{this.state.people.map((person) => {
return <Card
key={person.id}
id={person.id}
name={person.name}
imageURL={('http://localhost:3008/' + person.image)}
birthday={person.birth_year}
planetList={this.state.planets}
homeWorld={person.homeworld}
/>
})}
</div>
);
}
}
The expression [...Array(_page_limit).keys()] is a shortcut for creating an array of numbers between 0 and (_page_limit - 1), inclusive.
I am pretty new to developing in React and Javascript. I am bulding an application with a side menu. I wanted to display different components based on the selection in side menu. Can someone guide me how to do this. I am attaching my menu component and index code here.
class AppIndex extends Component {
constructor(props) {
super(props);
}
render () {
return (
<Navbar />
<div className="row">
<div className="col-md-2">
<MenuComponent/>
</div>
<div className="col-md-10">
// I need to add the components here based on selected item in menu
</div>
</div>
);
}
}
class MenuComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ul className=" nav nav-pills mr-auto flex-column">
<li className="nav-item">
Overview
</li>
<li className="nav-item">
Component1
</li>
<li className="nav-item">
Component2
</li>
<li className="nav-item">
Component3
</li>
<li className="nav-item">
Component4
</li>
<li className="nav-item">
Component5
</li>
</ul>
);
}
}
im sorry i didnt see your top level component.
Now from my experience, i wanna give you a little advice, don't let any child component render another component. try to avoid that as much as possible.
Here's what i would do.
This is the Top Level Component
class AppIndex extends Component {
constructor(props) {
super(props);
this.state = { component: '' };
this.selectComponent = this.selectComponent.bind(this); // dont forget to bind
}
selectComponent(event){ // this will take the name of the button thats beeing clicked and sets name of button to state
event.preventDefault();
this.setState({component: event.target.name});
}
render () {
let toRender = null;
switch(this.state.component)
{
case "component 1":
toRender = <Component1/>
case "component 2":
toRender = <Component2/>
case "component 3":
toRender = <Component3/>
}
return (
<Navbar />
<div className="row">
<div className="col-md-2">
<MenuComponent onClick = {this.selectComponent}/>
</div>
<div className="col-md-10">
{toRender} //here goes the component
</div>
</div>
);
}
}
this is the menu
const MenuComponent = ({onClick}) => { // you dont need a class component for this
return (
<ul className=" nav nav-pills mr-auto flex-column">
<li className="nav-item">Overview</li>
<li className="nav-item"> <button onClick = {onClick} name = "component 1">Component1</button></li>
<li className="nav-item"> <button onClick = {onClick} name = "component 2">Component2</button></li>
<li className="nav-item"> <button onClick = {onClick} name = "component 3">Component3</button></li>
</ul>
);
}
thats it.
easy.. You already have the name of the button in the top level component's state right?
send it down as props to the MenuComponent and on every button write something like,
here im assuming the name of the props the MenuComponent get is name
<li className="nav-item"> <button className = {this.props.name === "component 1"?"Active":""} onClick = {onClick} name = "component 1">Component1</button></li>