onClick Removing data from components - javascript

So basically I have two components. In Component 1 there is an img. In component 2 there is a button. I need when i press the button img disappears and also button disappears.
const Icons=()=> {
return (
<div className="_icons">
<div className="icons__Top">
<img src="./icons/-48.png" alt="Twitter"/>
<figcaption>Whatever</figcaption>
</div>
</div>
const Button= () => {
return (
<div className="button">
<Button variant="outlined" className="button__rightpage" >REMOVE</Button>
<caption className="text" ></caption>
</div>
)
}

There can be more than one solution,
1)I think you need to have one parent component for both components and make one state in parent component and then pass it in icon component and give it to img and default make it to false and then from button component change that state to true.
2)without parent component -> You can also use context api to change value directly from button component and hide img.

Related

rendering an additional pop up dialog on button click React

I am having issues with rendering a pop up loading screen. So assume i have a imported component called ( LoadingDialog ) and i want it to render when the state property, loading is true. When the user clicks a button on the current component, it triggers an api call which also changes the loading state to true, thus rendering the loading dialog.
I understand I can use conditional rendering to achive this, eg:
if(this.state.loading){
return (
<div>
<LoadingDialog />
</div>
)
}
else{
return(
<div> OTHER UI ELEMENTS </div>
)
but now i have a problem because, when my loadingDialog is rendered, my other ui (text area, background card, button ) all disappear, which is the opposite of what im trying to achieve. With this approach, i can only display my actual ui elements or the loading dialog.
I've tried separating the other ui elements into a separate container but it doesn't help as i need to call the api on click of an button and the entire problem i'm having now occurs in that child container.
I've also tried the above approach with passing a parent on click method as a prop and calling that when the button is clicked but somehow ended up with a recursive loop of the parent/child component
Heres my actual code:
if(this.state.loading){
return (
<div>
<LoadingDialog />
</div>
)
}
else{
return (
<div>
<Card className="center card">
<div className="row">
<div class="column" >
<TextField
id="outlined-name"
name="searchContent"
onChange={this.handleChange}
value={this.state.searchContent}
label="Name"
variant="outlined"
/>
</div>
<div className="column">
<Button
variant="outlined"
color="primary"
onClick={this.handleClick}
>
Search
</Button>
</div>
</div>
</Card>
</div>
);
}
and this is my handle click function:
handleClick = (event, name) => {
this.setState({loading : true})
fetch(uri)
.then(res => res.json())
.then(data => {
console.log(data);
this.setState({loading : false})
});
};
As i said before, I tried separating the UI bit on the else block to a different component but the problem still persisted. To summarise it again,
I can only render my actual ui or a popup box but not both at any given time.
I want to be able to render both at the same time, if needed.
I am very new to react and staying away from the likes of redux, hooks etc.
SOLVED Thanks to Chris G
So the issue was easily fixed by using a logical and operator to check if loading is true or false, like so {this.state.loading && <LoadingDialog />}
eg.
render(){
return(
<div>
{this.state.loading && <LoadingDialog />}
<div>
//REST OF THE STUFF THAT SHOULD BE RENDERED REGARDLESS
</div>
</div>
)
}

Javascript Onclick=window.open() function will open a new page every time I refresh the page?

So I have a DIV element that, when pressed, I want to open a new tab in a different window. The only problem is, whenever the page is refreshed or any other div element is pressed, th function is initiated as well and opens a page in another window. I'll include my code below, but I'm not sure why this is happening seeing as how I'm using onClick={window.open("https://www.thechinesewriter.com") Like I said, I only want a new tab to open when the div is pressed, not when any other items on the page are clicked or even when the page itself is refreshed.
import React from "react";
import "./Column1.css";
class Column1 extends React.Component {
render() {
return(
<React.Fragment>
<div className="rectImage">
<img className="imagePost" src={this.props.image} />
</div>
<div onClick={window.open("https://www.thechinesewriter.com")} className="downloadBut1">
<h2>
Source
</h2>
</div>
<div className="downloadBut2">
<h2>
Repository
</h2>
</div>
</React.Fragment>
)
}
}
export default Column1;
You need to call the function as a callback like this.
<div onClick={() => window.open("https://www.thechinesewriter.com")} className="downloadBut1">
Otherwise this gets called every time the component gets rendered.
You use an expression, which will execute everytime the component is rendered.
<div onClick={window.open("https://www.thechinesewriter.com")} className="downloadBut1">
You probably mean to use a function
<div onClick={() => window.open("https://www.thechinesewriter.com")} className="downloadBut1">

React | Virtual DOM element click event not triggering

I'm using Ant Design and React js for my Project.
Problem
I have a button in Popover and having click event for that button. The problem is button click event is not triggering.
JS Code
const content = (
<div className="RecurringPopover">
<button onClick={this.handleClick}> Popover Button </button>
</div>
);
Full Code with scenario in stackblitz
You have defined content outside the class and then supplying this.handleClick as a click handler to it. However outside class, this does not point to the class. You should define content inside class and use this.content to access that.
handleClick() {
alert('test');
}
// put it inside class
content = (
<div className="RecurringPopover">
<button onClick={this.handleClick}> Popover Button </button>
</div>
);
render() {
return (
<div>
<Row>
<Col span={12}>
// Use this.content instead of just content
<Popover content={this.content} title="Title">
<span type="primary">Hover me (Popover Button)</span>
Just bring the 'content' to inside the class, and pass it to component via 'this.content', it will work.

React.js - Creating Simple Accordion example

I'm relevantly new to React and I am having trouble on how to tackle this logic:
Essentially I am creating a table using flexbox, and I also want it so that when you click on one of the rows, it expands and reveals another row (for example, it will give a small description what it is about).
So far what I have is just the table.
class Application extends React.Component {
render() {
const renderDataRows = (
[
<div key={0} className='row'>
<div className='cell description'> Mortage Bill
</div>
<div className='cell amount'>$0,000,000</div>
<div className='cell amount'>$2.50</div>
<div className='cell amount'v>000%</div>
</div>,
<div key={1} className='row'>
<div className='cell description'> Electric Bill
</div>
<div className='cell amount'>$0,000,000</div>
<div className='cell amount'>$2.50</div>
<div className='cell amount'v>000%</div>
</div>,
]
)
const containerTable = (
<div className='table-container'>
{renderDataRows}
</div>
)
return (
<div>
{containerTable}
</div>
)
}
}
More specifically, what would be the best way to structure the hidden rows? Create as a child of the cells, or siblings?
I am assuming I will need state to keep in track what is current open, etc?
I've attached Codepen link to mess around
This can be done in the following way:
Let all the cells be in a single parent div and let the cell description be another sibling div (although using would be better). Put a class on the sibling div such as hidden. Not add a click handler on the cells div. Whenever this div is clicked, update the state with that div's id/key. Now use this to set the hidden class to the other divs. Compare this.state.key with the current id/key and show or hide accordingly. I am not giving the specific code.
Note: Instead of storing the divs in the renderDataRows, just put the data in it and map over it to create all the divs. That way you can easily manipulate the hidden class and any other variation in a single place without having to update it separately for each row of data.

Adding tab dynamically upgradeElement

When I add a tab with react, its parent element is already upgraded. So calling upgradElement has no effect and the added tab doesn't work.
What solution, recreate all tabs with the container and upgrade it ? React just update DOM component in this case I need to dismount component ?
How about calling componentHandler.upgradeElement() or componentHandler.upgradeDom() in the componentDidUpdate phase of the specific component
componentDidUpdate() {
componentHandler.upgradeElement(this.refs.myElement);
//or componentHandler.upgradeDom('MaterialTabs');
}
EDIT 1 Tab Component
componentDidUpdate() {
componentHandler.upgradeDom();
}
newTab() {
this.setState({
newtab: 1
});
}
render() {
return (<div className="mdl-layout mdl-js-layout mdl-layout--fixed-header" key={this.state.newtab}>
<button onClick={this.newTab.bind(this)}>Add Tab</button>
<header className="mdl-layout__header">
<div className="mdl-layout__tab-bar mdl-js-ripple-effect">
<Link to="/tabtest" hash="#scroll-tab-1" className="mdl-layout__tab is-active">Tab 1</Link>
<Link to="/tabtest" hash="#scroll-tab-2" className="mdl-layout__tab">Tab 2</Link>
{ this.state.newtab ?
<Link to="/tabtest" hash="#scroll-tab-3" className="mdl-layout__tab">Tab 3</Link> : null}
</div>
</header>
<div className="mdl-layout__content">
<section className="mdl-layout__tab-panel is-active" id="scroll-tab-1">
<div className="page-content">Tab 1</div>
</section>
<section className="mdl-layout__tab-panel" id="scroll-tab-2">
<div className="page-content">Tab 2</div>
</section>
{ this.state.newtab ? <section className="mdl-layout__tab-panel" id="scroll-tab-3">
<div className="page-content">Tab 2</div>
</section> : null}
</div>
</div>);
}
I did some tests and could reproduce the problem. What helped was to put the key attribute on the root element of the tab component. When adding a new tab this key must change and react will throw away the component and rerender completly. This way all material-design-lite properties get lost and after calling upgradeDom or upgradeElement it works.
React and Material-Design-Lite
Material-Design-Lite source
From https://facebook.github.io/react/docs/component-api.html.
forceUpdate
void forceUpdate(
[function callback]
)
By default, when your component's state or props change, your component will re-render. However, if these change implicitly (eg: data deep within an object changes without changing the object itself) or if your render() method depends on some other data, you can tell React that it needs to re-run render() by calling forceUpdate().
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. React will still only update the DOM if the markup changes.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.
In order to highlight the most important part of Christian Steinmann's answer:
Give the surrounding .mdl-js-tabs div element the tabs count as the key attribute.
Whenever a tab is added, the key will change and React will rerender the whole tabs component. This will then the MDL upgrade.

Categories

Resources