React: unwanted multiple instances of same component - reactjs

My Dashboard React component renders multiple child components. When I change the state of the parent component (dashboard), multiple instances of the child components are created. They are then stacked on top of each other:
as shown here
Obviously this is not what I want! Every component should only be displayed once.
Here is a simplified example:
state = {
goal : ''
}
_refresh = () => {
this.setState({
goal: '5'
})
}
render() {
return (
<div>
<div className='card'>
<div className='heading'>
<p style={{display: 'inline-block'}}>CURRENT WEIGHT</p>
{this.state.goal}
<button onClick={this._refresh}>hallo</button>
</div>
<CurrentPlot currentWeight={this.props.currentWeight} />
</div>
<div className='card'>
<div className='heading'>
<p>YOUR STATS</p>
</div>
<StatsPlot
xData={this.props.xData}
yData={this.props.yData}
/>
</div>
</div>
)
}
So whenever the button is clicked and the state is set, multiple instances of the plots are created.
And here is the root component from where the above component is rendered:
return (
<Switch>
<Route path='/dashboard' render={() => (
<Dashboard //all the props />
)}/>
more routes..
</Switch>
)
I would really appreciate any suggestions!

Related

How to pass static data from one component to another in React?

I have a plans component where I define the plan type, and I redirect to sign up component. I want to be able to show the plan type that the user has chosen, in my signup component?
I am trying to update the state like this:
export default class Plans extends Component {
constructor(props) {
super(props)
this.state = {
planType: '',
};
}
render() {
return (
<div>
<div className="billing_freq">Billed Monthly</div>
<form action="pro-invitation" method="post">
<input type="hidden" name="plan_type" value="monthly_pro" /> //I want to show this in signup
<div className="select_btn">
<input type="submit" name="submit" onClick={() => this.setState({planType: "monthly_pro"})} value="Invitation only" />
</div>
</form>
Signup: // a separate component
<label className="container"><span className="plan_name"></span> //PLAN TYPE HERE
</label>
class App extends Component {
render () {
return (
<BrowserRouter>
<div className="App">
<Switch>
<Route exact path='/plans' component={Plans} />
<Route exact path='/signup' component={Signup} />
</Switch>
</div>
</BrowserRouter>
How are you going to render Signup Component?
If from the routing, then there will be different way to achieve it and if you're using as a child component the pass as props like this -
<SignUp planType={this.state.planType} />
and access in Signup component as
<label className="container"><span className="plan_name"></span>{this.props.planType}
</label>
You want to give your planType state to the child component.
You can do this by doing this:
<Signup planType={this.state.planType} />
To use this in your child component use the props that you received from the parent, which is your planType state.
<label className="container"><span className="plan_name"></span>{this.props.planType}</label>

How to set other elements to hide when body element is set to full screen using react?

i want to hide some elements within body element when body element is set to full screen.
What i am trying to do?
within index.html file i have
<html>
<body>
<div id="root"></div>
<div id="modal"></div>
</body>
</html>
Within main application component i have
return (
<First/>
<TopComponent/>
<Switch>
<Route>
<div>
<div style={{display: 'flex'}>
<NavBar/>
<div className="content">
<Switch>
<Route exact path="/" render=
{this.render_items}/>
</Switch>
</div>
</Switch>
);
And in itemspage component when i click on fullscrenbtn it sets the body element to fullscreen.
extend default class ItemsPage extends React.Purecomponent (
open_full_screen = () => {
let elem = document.findElementsByTagName('body')[0];
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
}
render = () => {
return (
<button onclick=
{this.open_full_screen}>fullscreenbtn</button>
)
}
}
Now as you notice from above itemspage component it sets the entire elements in body tag on full screen.
Now the question is i don't want certain elements not to be displayed in fullscreen like the components before the content div
<First/>
<TopComponent/>
<Switch>
<Route>
<div>
<div style={{display: 'flex'}>
<NavBar/>
How can i do that. could someone help me with it. thanks.
You have to store the visibility value of those components in state. For example you state may look like below
components :{
First : "visible",
"Switch" : "hidden"
}
And your react JSX may look this :
<First style :`Visibility : ${this.state.component.First}`/>
<TopComponent/>
<Switch `Visibility : ${this.state.component.First}`>

React component redirect with onClick of table row that already has another onClick

I have a table row that already has an onClick, which is used to send data to a api in order to render new content.. Presently I have that api rendering to the landing page. I would however like the data to render to a separate page/pathway.
Do I want to use Redirect, Link, another onClick, etc.. Just confused on where to start and the best method to use.
const SearchResults = props => (
<tbody>
{ props.contracts.map((contract, i) =>
<tr key={i} data-id={contract.Id}
onClick={() => props.handleContract(contract.Fields.filter(field => field.DataField==="IDXT001").map(field => field.DataValue))}
>{contract.Fields.map( docs =>
<td key={docs.Id}><span id={docs.DataField}>{docs.DataValue}</span></td>)}
</tr> )}
</tbody>
)
Here is my main class page. I would like the Pdfs to load on a new page.
<SearchResults
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
handleContract={this.onClick}
/>
<Pdfs
labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs}
/>
Here is my App.js
class App extends Component {
render() {
return (
<div className="App">
<BrowserRouter>
<div>
<Header />
<Route exact path="/" component={Search} />
<Route path="/pdfs" component={Pdf} />
<Footer />
</div>
</BrowserRouter>
</div>
);
}
}
In your method you could use:
this.props.history.push({
pathname: '/yourpath',
state: { labels={this.state.labels}
contracts={this.state.contracts}
pdfs={this.state.pdfs} }
})
You can modify your onClick function to do some calculation on where you need to go based on where you are in the router history

Nested subcomponents in React + rendering new data

Help needed please,
I am currently learning react and I ran into an issues of some sort while creating a blog app.
I nested components within each other, however updated data is not received in subcomponent unless I refresh the page of the nested-component. Below is snippet of my codeWithin the AccountOverview component is another component(container) that handles a form. Once the form submits data and the backend processes the data, i expect that the AccountOverview component will render new info. However if i then go back to the parent (dashboard) and make an edit the AccountOverview component does't display newly created data except on a full-page refresh.
class Dashboard extends Component {
state = {}
componentDidMount(){
this.props.getCurrentProfile();
}
render() {
const { user } = this.props.auth;
const { profile, loading } = this.props.profile;
return (
<div style={{margin: "0", padding: "0"}}>
<Header title="Account Dashboard" />
<section id="accountPage" className="">
<div className="container">
<div className="row">
<Sidebar />
<main className="col-sm-9 col-md-9 account">
<div className="dashboard">
<AccountOverviewPanel
user={user} profile={profile} loading={loading}
/>
<PostTablePanel />
</div>
</main>
</div>
</div>
</section>
</div>
);
};
};
Is your submit action casusing your components to unmount.
I tried cloning your code. it seems to miss a file for keys hence couldn't run it

Trying to make a sub page (channel) in reactjs

I am trying to make the user able to create channels in my web app.
If you the see image below, there is a modal that take the input and use
that as the id of the page that will newly created.
My route is specified as:
require('./styles/main.scss');
render(
<Router>
<div>
<Route exact path="/" component={Home}/>
<Route exact path="/RecTest" component={RecTest}/>
<Route exact path="/Example" component={Example}/>
<Route path="/channels/:id" component={ (props) => (<Channel {...props}/>)} />
</div>
</Router>,
// Define your router and replace <Home /> with it!
document.getElementById('app')
);
And the modal is coded as:
class MakeChannelModal extends Component {
constructor(props){
super(props);
console.log("constructor");
this.state={
channelName: ''
}
this.clickHandler = this.clickHandler.bind(this);
this.inputChangeHandler = this.inputChangeHandler.bind(this);
}
inputChangeHandler(event) {
this.setState({
channelName: event.target.value
})
}
clickHandler() {
<Link to={{ pathname: '/channels/' + this.state.channelName }}></Link>
}
render(){
return(
<div className="ui active modal">
<div className="header">Create a New Channel</div>
<div className="loginbody">
<div className="fillout">
<div className="channelName">
<span>Channel Name: </span>
<Input
onChange = { this.inputChangeHandler }
placeholder="Channel Name"
label = "Channel Name"
value = { this.state.channelName } />
</div>
</div>
<Button onClick = { this.clickHandler }>
SUBMIT
</Button>
</div>
</div>
)
}
}
export default MakeChannelModal
I was assuming this to take the channel name input and direct the page to a Channel component with the id of df.
My Channel component is just blank right now.
The thing is, if I click SUBMIT in the modal, it does not do anything.
Doesn't even show an error.
What am I doing wrong?
clickHandler() should be a function that changes pathname, making Router to draw another component, but it tries to draw React component by itself instead (not quite successfully though, because this function doesn't actually returns anything).
I believe you should either use props.history.push() in onClick(), or make <Button /> a <Link />.
Solution 1: (preferable, if you want a <Button>)
Replace your clickHandler() with this:
clickHandler() {
this.props.history.push('/channels/' + this.state.channelName);
}
Solution 2: (still would work)
Replace your <Button ... /> component with this:
<Link to={{ pathname: '/channels/' + this.state.channelName }}>
SUBMIT
</Link>
SO answer about history.push(): https://stackoverflow.com/a/43298961/6376451

Resources