I am creating a really simple app in react. It will have a number of pages with minimum data on it. I am looking for the simplest method to switch between the pages with as little complexities as possible.
This is my current code:
render() {
return (
<div className="App test">
<nav className="navbar pure-menu pure-menu-horizontal">
<a href="#" className="pure-menu-heading pure-menu-link">
Page 1
</a>
{
}<ul className="pure-menu-list">
<li className="pure-menu-item">Page 2</li>
<li className="pure-menu-item">Page 3</li>
<li className="pure-menu-item">Page 4</li>
</ul>
}
</nav>
<main className="container">
<div className="pure-g">
<div className="pure-u-1-1">
<p>
Page 1 text
</p>
<p>
Page 2 text
</p>
<p>
Page 3 text
</p>
<p>
Page 4 text
</p>
</div>
</div>
</main>
</div>);
}
}
Is there a standard to switch between the content? (Page text 1,2,3,4).
How simple? :). Simplest method possible would be to hold a pageNumber state in your component and only render a particular page when it is that number. Call setPageNumber with a parameter to see the component render different pages.
This is obviously not the best solution or scalable.
class App extends React.Component {
constructor() {
super();
this.state = {
pageNumber: 0
};
}
onClickLink = (pageNumber) => {
this.setState({ pageNumber });
}
render() {
<div className="pure-u-1-1">
{this.state.pageNumber === 0 ? <p></p> : null}
{this.state.pageNumber === 1 ? <p></p> : null}
{this.state.pageNumber === 2 ? <p></p> : null}
{this.state.pageNumber === 3 ? <p></p> : null}
</div>
}
}
The better way is to add onClickLink function to the link of pages, and put all your pages in an array, and in the place where you want it to be have something like this:
onClickLink = (pageNumber, event) => {
this.setState({ pageNumber });
}
render() {
<ul className="pure-menu-list">
<li className="pure-menu-item"><a href="#" className="pure-menu-link" onClick=onClickLink.bind(null, 2)>Page 2</a></li>
</ul>
<div className="pure-u-1-1">
<p>arrayOfPageComponents[this.state.pageNumber]</p>
</div>
}
So the function is bound to the link with the value of page number (in my example 2), when it's called, it's called with 2, so state will be changed to 2, this change will be detected by React and the component will be re-rendered, now reading 2nd value from the array of pages.
Related
I receive this error:
TypeError: this.state is null
Have code like this, but it does not work .... Any idea why?
I want to change the text of a label (reanalyzeButton)
Read several docs and tutorials and it seem it should work. No idea why it behaves like this.
This is inherited code I work with using React 0.13
var ProjectHeader = React.createClass({
displayName: 'ProjectHeader',
intervalId: null,
state: {
projectjson: [],
label: '',
},
componentDidMount() {
// Now we need to make it run at a specified interval
this.intervalId = setInterval(this.refresh, 1000);
this.setState({ label: '<span><i className="octicon octicon-sync" /> Project queued for analysis: <strong>{queuePosition}</strong>.</span>'});
},
refresh : function(){
if (this.state.projectjson.analysis_status == 'succeeded') {
clearInterval(this.intervalId);
this.setState({label: '<A onClick={this.analyzeProject} title="Request an analysis of the project"><i className="octicon octicon-sync"/> Check for new commits</A>'});
}
render : function(){
if (props.project.analysis_status == 'in_progress') {
//reanalyzeButton = <A onClick={this.analyzeProject} title="Request a re-analysis of the project"><i className="fa fa-refresh fa-spin" /> Analysis in progress</A>
reanalyzeButton = this.state.label
} else if ((!props.project.analyze) || props.project.analysis_priority == 0) {
//reanalyzeButton = <A onClick={this.analyzeProject} title="Request an analysis of the project"><i className="octicon octicon-sync"/> Check for new commits</A>
reanalyzeButton = this.state.label
} else {
//reanalyzeButton = <span><i className="octicon octicon-sync" /> Project queued for analysis: <strong>{queuePosition}</strong>.</span>
reanalyzeButton = this.state.label
}
return <div className="project-header" itemScope itemType="http://schema.org/Code">
<div className="row">
<div className="col-xs-12 col-sm-9">
<div className="clearfix">
{projectHeader}
</div>
</div>
<div className="col-xs-12 col-sm-3">
<span className="qc-badge">
{badge}
</span>
</div>
</div>
<div className="row">
<div className="col-xs-12">
<ul className="meta">
{fetchStatus}{projectInfo} <li>{reanalyzeButton}</li>
</ul>
<ul className="tags hidden-xs">
{tagList}
</ul>
</div>
</div>
You need to specify a getInitialState method in order to set the initial state. See here: https://reactjs.org/docs/react-without-es6.html#setting-the-initial-state
using componentDidMount() to initialize materialize js works fine as shown in the documentation
componentDidMount() {
document.addEventListener("DOMContentLoaded", function() {
var elems = document.querySelectorAll(".sidenav");
M.Sidenav.init(elems, {});
});
}
but whenever I convert my component to a functional one and run the same initialization inside useEffect it doesn't work and my sideNav isn't initialized
the whole code
import React, { Fragment, useEffect } from "react";
import M from "materialize-css/dist/js/materialize.min.js";
export const Navbar = () => {
useEffect(() => {
document.addEventListener("DOMContentLoaded", function() {
var sidenav = document.querySelectorAll(".sidenav");
M.Sidenav.init(sidenav, {});
});
}, []);
return (
<Fragment>
<div className="navbar-fixed">
<nav className="teal darken-3">
<div className="nav-wrapper mx-4">
<a href="#!" className="brand-logo">
<i className="far fa-id-badge" />
EMS
</a>
<a href="#!" className="sidenav-trigger" data-target="mobile-nav">
<i className="material-icons">menu</i>
</a>
<ul className="right hide-on-med-and-down">
<li>
Settings
</li>
<li>
Register
</li>
<li>
Login
</li>
</ul>
</div>
</nav>
</div>
<ul className="sidenav blue-grey darken-4" id="mobile-nav">
<h3 className="teal-text ml-2">EMS</h3>
<li>
<div className="divider blue-grey darken-2"></div>
</li>
<li>
<a href="profiles.html" className="white-text">
Settings
</a>
</li>
<li>
<a href="register.html" className="white-text">
Register
</a>
</li>
<li>
<a href="login.html" className="white-text">
Login
</a>
</li>
</ul>
</Fragment>
);
};
i think the issue is with the document.addEventListner
you should know when you just want to useEffect works like componentDidMount you should pass empty array as the second parameter. like below
useEffect(() => {
var sidenav = document.querySelectorAll(".sidenav");
M.Sidenav.init(sidenav, {});
}, []);
in this way useEffect only run once.
and notice : when componentDidMount fires it means all HTML is already in the DOM. so you don't need any listener for data fully loaded.
and please note that effects in react are just effects, do not think them as lifecycles.
I made a Table component and inside every column I've put jsx syntax return function to render the HTML, but inside return of render, I want to change data of component with this.firstName = item ; (item is inside render function) but I can't access this.
How can I access this inside return of render in Vue.js ?
here is my code :
field: 'id',
caption: '',
sortable: false,
render: (item) => (h) => {
return (
<td class="uk-text-middle uk-text-center">
<div class="uk-inline">
<span class="more-option" uk-icon="icon: more"></span>
<div class="uk-padding-small" uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav uk-text-right">
<li>
<button onClick={ () => {console.log(this)} }>
<span class="uk-margin-small-left" uk-icon="icon: file-edit"></span>
edit
</button>
</li>
<li>
<a href="#">
<span class="uk-margin-small-left" uk-icon="icon: trash"></span>
delete
</a>
</li>
</ul>
</div>
</div>
</td>
);
}
Because you use nested anonymous functions, the internal function scope of this is different.
You can bind this, or assign this to another variable in upper function
(item) => {
const self = this;
return (h) => (
<button onClick={ () => {console.log(self)} }>
<span class="uk-margin-small-left" uk-icon="icon: file-edit"></span>
edit
</button>
);
}
I have one component as follow:
var SingleEditableModule = React.createClass({
getInitialState: function() {
return {
selected: false
};
},
show_overlay: function() {
$('.overlay').fadeIn();
},
render: function() {
var show_overlay = this.show_overlay;
return (
<div className="large-4 small-12 columns">
<h3 className="title">{this.props.data.title}</h3>
<div className="month">
<p>
{this.props.data.month}
</p>
</div>
<div className="img-holder">
<div
id={this.props.data.id}
onClick={show_overlay}
className="action_wrapper">
<span className="swap_trigger"></span>
<span className="action">
{this.props.data.action}
</span>
</div>
</div>
<h4>{this.props.data.title_description}</h4>
<p>{this.props.data.description}</p>
</div>
);
}
});
I want to assign a CSS class to this component based on "className" gained from "get_campus_id":
var Overlay = React.createClass({
close_overlay: function() {
$('.overlay').fadeOut();
},
get_campus_id: function(className) {
console.log(className);
},
render: function() {
var options = [],
get_campus_id = this.get_campus_id;
this.props.data.map(function(el, i){
options.push(<li
className={el.className}
onClick={get_campus_id.bind(null, el.className)}
key={i}>{el.location}</li>);
});
return (
<div className="overlay">
<div className="overlay-content">
<header className="clearfix">
<h3 className="float-left">Select your campus rotation</h3>
<div onClick={this.close_overlay} className="float-right close">
<span className="cancel">Cancel</span>
<span className="x">x</span>
</div>
</header>
<ul>
{options}
</ul>
<footer>
</footer>
</div>
</div>
)
}
});
"SingleEditableModule" represents an empty module which can be populated based on the value returned from "get-campus_id".
Full github url: https://github.com/WebTerminator/Hult
You cannot change the state of one component from another component. The best you can do is have both of them being children of a parent component, and then pass parameters as a prop. You can then use componentWillReceiveProps(nextProps) to intercept new props coming in (if you want to then modify a state based on that).
I'm beginner with react and i got a problem,
I want to update state to a component by one another component .
There is my html :
<div id="leftmenu"></div>
<div id="systeme"></div>
I actually hide component in my LeftMenu component with :
var LeftMenu = React.createClass({
getInitialState: function() {
return {modif: false};
},
render: function() {
return(
<div className="col s2">
<ul id="slide-out" className="side-nav fixed">
<li><a className={this.state.modif ? 'validate' : ' validate hidden'}><i className="material-icons right">done</i>CONFIRMER ET REBOOT</a></li>
<li><a className={this.state.modif ? 'cancel' : 'cancel hidden'}><i className="material-icons right">stop</i>TOUT ANNULER</a></li>
</ul>
</div>
)
}
});
I want modify modif state when my Systeme component fire an action,
It is possible ?
Thank's ;)