React hiding components without react router - javascript

I have 4 components. The app component which has everything, a menu component which has two link options: General and reviews, and the two components I’m trying to hide/show: General component and reviews component.
How can I make it so that the menu component originally shows the General component and if I click on the reviews link, it would hide the General component and show the reviews components. Then if you click on the General component link, it would hide the reviews component and show the General component. I don’t need to use router since I’m not changing links, I just need to hide and show components.
I have the idea of adding an active state on the app state but not sure how it would work.

In your App component, have a state item currentView, which would hold the page you would like to display, Either by using an if and else, or just hiding them when they are not the option selected
class App extends React.Component {
constructor() {
this.state = {
currentView: 'general' // general|reviews|etc...
}
this.changeView = this.changeView.bind(this);
}
changeView(viewName) {
this.setState({
currentView: viewName
});
}
render() {
return (
<div className="menu">
{this.state.currentView !== 'general' && (
<a onClick={() => this.changeView('general')}>
General
</a>
)}
{this.state.currentView !== 'reviews' && (
<a onClick={() => this.changeView('reviews')}>
Reviews
</a>
)}
</div>
);
}
}

Related

how to add tab component and load pages in tabs in react js app?

I have a react js app, that i'm working on. I created a myfirstcomponent, which call a rest api and displays some json data. Now I want to expand my app and add more components, say mySecondComponent. but i want to make it such that i create tabs for this. so I researched and based on the tutorials, i created a tabs and a tab component as well. Now, i want to modify my render method in my app.js file , such that i can render my components within the tab component. so i tried the following, added the Tabs and Tab component inside the app div, now i need to show/hide the components based on the selected tab. . I'm new to react so, i want to make sure i am headed in right direction. is this the right way of doing this in reactjs?
render() {
return (
<div className="app">
<Tabs tabs={['first', 'second']} selected={ this.state.selected }
setSelected={ this.setSelected }>
<Tab isSelected={ this.state.selected === 'first' }></Tab>
<Tab isSelected={ this.state.selected === 'second' }></Tab>
</Tabs>
<myfirstcomponent className="compnent"/>
<mySecondcomponent className="compnent"/>
</div>
);
}
app.js file
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<myfirstcomponent className="App-com"/>
</div>
);
}
}
export default App;
Tabs
import React from 'react';
class Tabs extends React.Component {
render() {
return (
<div style={{ width: '30%' }}>
<ul className="nav nav-tabs">
{
this.props.tabs.map(tab => {
const active = (tab === this.props.selected ? 'active ' : '' );
return (
<li className="nav-item" key={ tab }>
<a className={"nav-link " + active + styles.tab} onClick={ () =>
this.props.setSelected(tab) }>
{ tab }
</a>
</li>
);
})
}
</ul>
{ this.props.children }
</div>
);
}
}
export default Tabs;
Tab.js
import React from 'react';
class Tab extends React.Component {
render() {
if (this.props.isSelected) {
return (
<div>
{ this.props.children }
</div>
);
}
return null;
}
}
export default Tab;
I don't think that approach is right. You should be using routing inside the tab component and links to the routes. Pluralsight site has a pretty good example on how to implement what you want to do.
https://app.pluralsight.com/guides/how-to-create-nested-tab-routes-with-react-router
NOTE: This might not be exact answer for your question.
I think you can use material-ui for creating the tabs component.
Here is a good example with the code. https://material-ui.com/components/tabs/
And also if you are new to react. I would encourage to learn/write functional components rather than class based components. Because in class based components the state management and props with the "this" keyword is very confusing.

In React, what's the preferred design pattern for communicating data between a nested node and a sibling in a different branch?

I have a scenario where I'm a bit confused on how to approach. I feel like there's a lot of refactoring to be done if I were to communicate from the lowest level all the way back up to the parent. I'm very new to using React (a few days now) and I don't know if there's an easier solution to communicate data between components. I've read some sources that said child to parent to other child is best, but I haven't seen mentions of great-great-grandchildren to parent to a child. I've seen mentions about Context API, ComponentDidMount/Update, but I'm not sure what the best approach is.
I'm creating a data explorer on this webpage so we have the RootComponent, LeftPanel, and Graph component.
The LeftPanel holds an Explorer component, which will go through multiple levels of data. On the last level of data, if clicked, it should display a Graph component (through conditional rendering).
ex:
The Parent
export default class RootComponent extends React.Component {
render() {
return (
<div className="flex-row flex-grow">
<LeftPanel />
//Need to conditionally render this
<Graph />
</div>
)
}
}
LeftPanel is a container within the parent that will hold an explorer
export default class LeftPanel extends React.Component {
... (bunch of other logic)
render() {
return (
<Card className="flex-column default-vertical-spacing">
<div className="content">
<Explorer
..........>
</div>
</Card>
)
}
}
Explorer holds data as well as a "Pill" or button to click which will show further levels of data
export default class Explorer extends React.Component<IExplorerProps> {
... (bunch of logic)
render() {
if(!this.props.items || this.props.items.length == 0){
return <span>Loading</span>
}
return (
<ExpandablePill
............../>
)
}
}
ExpandablePill is data that can keep going downward
export default class ExpandablePill extends React.Component<ExpandablePillProps, ExpandablePillState> {
render() {
...
//Here I want to do: If this ExpandablePill was clicked AND it has no children, display a graph.
}
}
This is under the parent RootComponent but I need to know if an ExpandablePill with no levels left was clicked to display a graph (or make it known to the parent-RootComponent that I can display a graph now)
export default class Graph extends React.Component {
render() {
return (
<LineChart
...
</LineChart>
);
}
}
Any suggestions would be appreciated! I apologize if this is a duplicate.

Passing React Refs in a Higher Order Components

I have a component architecture in which there is a Navigation component that contains several unique Navigation Button components. The Navigation Button components each contain a Nav Item component made of an A-tag and an I-tag.
It looks like:
Navigation > Navigation Button > Nav Item > A-tag/I-tag
I'm tasked with implementing some DOM manipulation functionality and will need to access unique Refs placed on a Nav Item component's A-tag and I-tag.
The Refs on both the A-tag and the I-tag will need to be unique and relevant to their parent Navigation Button component.
Lastly, I will need to eventually store all of these Refs in an array-like structure and send them back to the top-level Navigation component for state management.
I've tried creating a ref at the Button Component level and passing it down as a prop to be placed on the A-tag and I-tag, but the value becomes null.
It seems that there are many situations in which Refs are overwritten and generating them dynamically is proving to be challenging.
QUESTION : Does anyone have any suggestions on how I can successfully give the Nav Item's A-tag and I-tag unique refs, which can later be stored in a data structure with Refs from other A-tags and I-tags, which will be used by the parent Navigation component?
Though I've simplified the code a lot, the general component architecture looks like this:
Several unique button components that look like:
class ButtonOne extends React.Component {
constructor(props) {
super(props);
// Some state stuff happens here
this.buttonOneRef = React.createRef();
}
render(
<Nav.Item
buttonRef = { this.buttonOneRef }
/>
);
export default ButtonOne
}
A NavItem component that looks like
class NavItem extends React.Component {
constructor(props) {
super(props);
// Some state stuff happens here
}
const dropdownIcon = (
<React.Fragment>
<i ref={`${this.props.buttonRef}-${this.props.label}-i`/>
</React.Fragment>
)
const link = (
<React.Fragment>
<a ref={`${this.props.buttonRef}-${this.props.label}-a`>{this.props.label}</a>
</React.Fragment>
)
return (
<li>
{link}
{dropdownIcon}
</li>
export default NavItem
}
And a Navigation component that looks like
class Nav extends React.Component {
constructor(props) {
super(props);
// Some state stuff happens here
}
render() {
const childrenItems = React.Children.map(this.props.children), (child, index) => {
return (
React.cloneElement(iteem, {
// Some Props here
})
)
}
}
return (
<nav>
<ul>
{childrenItems}
</ul>
</nav >
)
export default Nav
}

sharing a common state among duplicate react component in React JS

I have one doubt regarding state of component. I have one tile component. On click of tile component I am toggling the details of tile component.
/* ---- Tile component ---- */
import React, { Component } from 'react';
import TileDetail from './TileDetail';
class Tile extends Component {
constructor(props) {
super(props);
this.state = {
isTileDetailOpened:false
};
this.showTileDetails=this.showTileDetails.bind(this);
}
showTileDetails(networkName){
this.setState({isTileDetailOpened:!this.state.isTileDetailOpened});
alert(networkName);
}
render() {
const isTileDetailOpened = this.state.isTileDetailOpened;
return (
<li className={ !this.state.isTileDetailOpened ? "tile-item" : "tile-item-with-detail" }>
<div onClick={(e) => this.showTileDetails(this.props.objTile.network_name)}>
{this.props.objTile.network_name}
</div>
{this.state.isTileDetailOpened ? <TileDetail /> : <div/>}
</li>
);
}
}
export default Tile;
/* ---- Tile Detail component ---- */
import React, { Component } from 'react';
class TileDetail extends Component {
render() {
return (
<div className="tile-detail">
<p>TileDetails</p>
</div>
);
}
}
export default TileDetail;
As you can see, I am toggling the tile detail on click of tile click and its working fine.
I am rendering collecting of tiles on my page. And it works fine if I click on individual tile. But What I want if I am seeing the detail of one tile other tile details should be always hidden.
Could you please guide me on this. Completely new on React JS
You'll have to make use of the parent component of the Tile to achieve this. In the parent component have a state like currentlyTileDetailOpened. In showTileDetails call a method via props to set the value of this state(currentlyTileDetailOpened) to the id of the current Tile. Pass this state to the Tile component as a prop. In render method of Tile, check the prop instead of state and render it like
{this.props.currentlyOpenedTile === tile.id ? <TileDetail /> : null}
I just did this with a pagination control unit I made by storing the page info in Redux, and then making a special option in the second paginator so that it just used the Redux data instead of "double performing" the same work (and thus also not going out of sync with the first paginator).
It's like this (you could do the same with setting the parent's state (ie: first common ancestor):
<Pagination
pageSize={25}
items={(!this.state.fuzzyMatches.length)
? this.props.businesses
: this.state.fuzzyMatches}
onChangePage={(pagerState) => this.handlePageChange(pagerState)}
activePage={this.props.activePage}
isEmpty={((this.state.search.length > 0) &&
(this.state.fuzzyMatches.length === 0))}
bottom // bottom = true
bottomData={this.props.pagination} // get data from here
/>
Now, inside the paginator, instead of the normal logic, it does this:
render() {
const pager = (this.props.bottom)
? this.props.bottomData
: this.state.pager
The bottom = true prop is actually just to handle a slight CSS difference, but you can see, the first paginator creates the details, and the second one simply uses those instead of duplicating. I have told the second component to skip all its internal work and just use the data that is passed in.

2 different ways to create React component

I was following a react tutorial and this is the example code the author has given to create a basic React component:
const React = require('react')
const ReactDOM = require('react-dom')
const App = () => {
return (
<div className='app-container'>
<h1>Hello</h1>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'))
He claim it's ES6.
But then I saw another way to create component.
class App extends React.Component {
render(){
return <h1>Hello</h1>;
}
}
hmm I'm confused now. Is there any standard way of doing things in react?
In React you can create the so-called stateful and stateless functional components. Stateless components are simple reusable components which do not need to maintain state. Here is a short demo (http://codepen.io/PiotrBerebecki/pen/yaoOKv) showing you how you can create them and how they can access props passed from the parent (stateful component).
A simple example may be a theoretical App stateful component on Facebook.com. It could maintain state to track if user is logged in or logged out. Then in its render() method it would show a LoginLogout stateless button component passing to it the current state. The LoginLogout stateless component would then show either:
'Log In' text if user is not logged in, or
'Log Out' text if user is logged in.
You can learn more about stateful vs stateless components here: ReactJS difference between stateful and stateless and here React.createClass vs. ES6 arrow function
// Stateful component
class FacelookApp extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false
};
}
receiveClick() {
this.setState({
isLoggedIn: !this.state.isLoggedIn
});
}
render() {
return (
<div>
<h4>Welcome, I'm a stateful parent called Facelook App</h4>
<p>I maintain state to monitor if my awesome user logged
in. Are you logged in?<br />
<b>{String(this.state.isLoggedIn)}</b>
</p><br />
<p>Hi, we are three stateless (dumb) LoginLogout buttons
generated using different ES6 syntax but having the same
functionality. We don't maintain state. We will tell
our parent if the user clicks on us. What we render is
decided by the value of the prop sent to us by our parent.
</p>
<LoginLogout1 handleClick={this.receiveClick.bind(this)}
isLoggedIn={this.state.isLoggedIn}/>
<LoginLogout2 handleClick={this.receiveClick.bind(this)}
isLoggedIn={this.state.isLoggedIn}/>
<LoginLogout3 handleClick={this.receiveClick.bind(this)}
isLoggedIn={this.state.isLoggedIn}/>
</div>
);
}
}
// Stateless functional components
// created in 3 equally valid ways
const LoginLogout1 = (props) => {
return (
<div>
<button onClick={() => props.handleClick()}>
LoginLogout v1 --- {props.isLoggedIn ? 'Log Out' : 'Log In'}
</button>
</div>
);
};
// or
const LoginLogout2 = ({handleClick, isLoggedIn}) => (
<div>
<button onClick={() => handleClick()}>
LoginLogout v2 --- {isLoggedIn ? 'Log Out' : 'Log In'}
</button>
</div>
);
// or
const LoginLogout3 = ({handleClick, isLoggedIn}) => {
return (
<div>
<button onClick={() => handleClick()}>
LoginLogout v3 --- {isLoggedIn ? 'Log Out' : 'Log In'}
</button>
</div>
);
};
ReactDOM.render(
<FacelookApp />,
document.getElementById('app')
);
Both of them are "equally standard".
Though the syntax for the second case is off. It should read class App extends React.Component {
The second approach is the most generic one, because it allows for state, extra functionality besides the render and Component lifetime methods etc. But when you have "functional" components, which just display something based on their props, you have the first approach as a shorthand for a class with just the render method. When calling .render React knows how to deal with the two cases.
const App = () => {
return (
<div className='app-container'>
<h1>Hello</h1>
</div>
)
}
is called "stateless function component", which can not have state
https://facebook.github.io/react/docs/reusable-components.html#stateless-functions
the another one is a normal component.

Categories

Resources