React: Toggle content in another component - javascript

I'm new to React and I'm stuck in this problem. I have a toggle component that is rendering a button to show/hide data aswell as the data that is being rendered.
I want to separate both the button and the data so I can display the content in another component, and being able to hide it and show it from the toggle component, if it makes sense.
Here is a picture to demonstrate what I'm wishing to do.
Toggle Example
The toggleComponent.js that contains the button and the data :
import React, { Component } from 'react';
export default class toggleComponent extends React.Component{
constructor(){
super();
this.state={
isShowBody: false
}
}
handleClick = (event) => {
this.setState({ isShowBody: !this.state.isShowBody })
}
checkbox = () => {
return (
<div >
<span className="switch switch-sm" >
<label>
<input type="checkbox" name="select" onClick={this.handleClick.bind(this)}/>
<span />
</label>
</span>
</div>
)
}
content = () => {
return (
<div>
Displaying text
</div>
)
}
render() {
return (
<div>
{this.checkbox()}
{this.state.isShowBody && this.content ()}
</div>
);
}
}

Just make another component named content.js. Import ContentComponent inside ToggleComponent and render it using flag.
Stackblitz Demo
Solution:
Toggle Component
import React, { Component } from "react";
import ContentComponent from "./content.js";
export default class toggleComponent extends React.Component {
constructor() {
super();
this.state = {
isShowBody: false
};
}
handleClick = event => {
this.setState({ isShowBody: !this.state.isShowBody });
};
checkbox = () => {
return (
<div>
<span className="switch switch-sm">
<label>
<input
type="checkbox"
name="select"
onClick={this.handleClick.bind(this)}
/>
<span />
</label>
</span>
</div>
);
};
render() {
return (
<div>
{this.checkbox()}
{this.state.isShowBody && <ContentComponent />}
</div>
);
}
}
Content Component
import React, { Component } from "react";
export default class ContentComponent extends React.Component {
content = () => {
return <div>Displaying text</div>;
};
render() {
return <div>{this.content()}</div>;
}
}

Related

getting material-ui TextField value onsubmit

I want to get the value of TextField input and render the message conditionally. I tried this one, its working but this one is functioning dynamically because I used onChange. I want to achieve the same but using onSubmit on <Button> Is there anyway to do that?
import React from 'react';
import { Component } from 'react';
import Button from '#mui/material/Button';
import { TextField } from '#mui/material';
class App extends Component
{
state = {
myValue: null,
}
handleChange = (e) => this.setState({
myValue: e.target.value
})
render() {
return (
<div>
<TextField
value={this.state.myValue}
onSubmit={this.handleChange}
/>
<button >Get Weather</button>
{this.state.myValue ? <p>value inputed </p>: <p>no input</p>}
</div>
)
}
}
export default App;
Using Refs is what you need. You can get the current value of your input by clicking a button and only then change the state.
Demo
import React, { createRef } from "react";
import { Component } from "react";
import { TextField } from "#mui/material";
class App extends Component {
constructor(props) {
super(props);
this.textInput = createRef();
this.state = {
myValue: ""
};
}
showRefContent = () => {
this.setState({
myValue: this.textInput.current.value
});
};
handleChange = (e) =>
this.setState({
myValue: e.target.value
});
render() {
return (
<div>
<TextField inputRef={this.textInput} />
<button onClick={this.showRefContent}>Get Weather</button>
<p>
{this.state.myValue.length > 0
? `text:${this.state.myValue}`
: "no text"}
</p>
</div>
);
}
}
export default App;
you just need to you onkeydown instead onsubmit.
<TextField
value={this.state.myValue}
onKeyDown={this.handleChange}
/>
or use
<form onSubmit={handleChange }>
<TextField
value={this.state.myValue}
onKeyDown={this.handleChange}
/>
<button type="submit">submit</button>
</form>

How to get the whole block of data using reactjs?

I've created a component which displays only block[0] value, it is not showing the whole block value.
For Example, if I write :
HI
Stackoverflow
It is showing only "Hi", It's not showing the full content of the field.
Can anyone help me in getting the whole data whatever I write in that input field?
import React from "react";
import { Editor } from "react-draft-wysiwyg";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
export default class Edit extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<Editor value={this.props.value} onChange={this.props.onChange} />
</div>
);
}
}
App component:
import React from "react";
import Body from "./Body";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
body: ""
};
}
changeBodyHandler = value => {
console.log(value.blocks[0].text);
this.setState({
body: value.blocks[0].text
});
};
render() {
return (
<div>
<Body
label="Body"
name="body"
value={this.state.body}
onChange={this.changeBodyHandler}
/>
</div>
);
}
}
export default App;
Here is the whole code:
"https://codesandbox.io/s/compassionate-tereshkova-89fm2"
Can anyone please help me with this?
Each line to list, then map(), join() with \n would be fine
this.setState({ body: value.blocks.map(x => x.text).join("\n") });
import React from "react";
import Body from "./Body";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
body: ""
};
}
changeBodyHandler = value => {
this.setState({ body: value.blocks.map(x => x.text).join("\n") });
};
render() {
console.log(this.state.body);
return (
<div>
<Body
label="Body"
name="body"
value={this.state.body}
onChange={this.changeBodyHandler}
/>
</div>
);
}
}
export default App;
Try it online:
If you want with break line like as it is in editor, add <p> tag while concatination.
changeBodyHandler = value => {
let data =value.block;
let text = "";
data.map(index => {
text = text +"<p>" +index.text+"</p>";
});
this.setState({
body: text
});
};
And if you want to display the data in same way somewher use dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{__html: this.state.body}} />

Using button in one component to render another component in main (App) component

I am trying to display/hide one component which is ItemMain and which is imported to the main App component using button in another component which is NavLogoNew. I tried to do this in many different ways but it looks like the button doesn't know if it's clicked, when I change true/false manually it works. In web I found a lot of stuff about situations when only two components are involved, but nothing like this. My code:
App
import React from 'react';
import './App.css';
import { tsPropertySignature } from '#babel/types';
import { statement } from '#babel/template';
import NavBar from './../Components/Navigation/NavBar/NavBar.js';
import ItemMain from './../Components/Item/ItemMain/ItemMain.js';
import ItemList from './../Components/Item/ItemList/ItemList.js';
import NavButtonTop from './../Components/Navigation/NavButton/NavButtonTop/NavButtonTop.js';
import NavLogoNew from './../Components/Navigation/NavButton/NavButtonNew/NavLogoNew.js';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
visible: !this.visible
})
}
render() {
return (
<div className="App">
<NavBar />
{this.state.visible ? <ItemMain /> : null}
<ItemList />
<NavButtonTop name='UP'/>
</div>
);
}
}
export default App;
NavLogoNew:
import React from 'react';
import './NavLogoNew.css';
import ItemMain from './../../../Item/ItemMain/ItemMain.js'
class NavLogoNew extends React.Component {
render() {
return (
<button
className='NavLogoNew'
onClick={this.props.click}
>
{this.props.name}
</button>
);
}
}
export default NavLogoNew;
Your handleClick function is lacking something
use !this.state.visible so change from the below
handleClick(){
this.setState({
visible: !this.visible
})
}
to
handleClick = () => {
this.setState({
visible: !this.state.visible
})
}
pass the handleClick function to the NavLogoNew as follows
<NavLogoNew onClick = {this.handleClick} />
inside of the NavLogoNew component you should invoke it as follows
class NavLogoNew extends React.Component {
render() {
return (
<button
className='NavLogoNew'
onClick={() => this.props.onClick()}
>
{this.props.name}
</button>
);
}
}

How to change component inside of render with a button click?

I'm new at programming at all especially in ReactJS. Actually I'm running into a problem.
I just wanna change the page. As simple as it sounds for me it is a 2 day Google-Search-Nothing-Found-Adventure without fun.
I made a component called <Frontpage />
It renders directly in the beginning but I want to change it with a click on a button.
This is my code:
import React from 'react';
import './App.css';
import Frontpage from './Frontpage'
import Question from './components/Question'
class App extends React.Component {
constructor() {
super()
this.state = {
showComponent: true,
}
}
handleClick() {
if (this.state.showComponent) {
return <Question />
} else {
console.log("Something went wrong!")
}
// console.log("The button was clicked!")
// document.getElementById('page')
// document.getElementsByClassName('App-Header')
}
render() {
return (
<div className="App">
<header className="App-header">
<div id="page">
<Frontpage />
</div>
<button id="button" onClick={this.handleClick}>Los geht's</button>
</header>
</div>
);
}
}
export default App;
When I click it, it always says: "TypeError: Cannot read property 'state' of undefined"
I tried a lot but nothing worked.
Try something like this. Change you handleClick function to an arrow function and render the component based on the state.
Update: notice that i have used a Fragment to wrap the button and Question elements/components
import React,{Fragment} from 'react';
import './App.css';
import Frontpage from './Frontpage'
import Question from './components/Question'
class App extends React.Component {
constructor() {
super()
this.state = {
showComponent: false,
}
}
handleClick =()=> {
this.setState({showComponent:true})
}
render() {
return (
<div className="App">
<header className="App-header">
<div id="page">
{this.state.showComponent? <Fragment><Question /><button id="button" onClick={this.handleClick}>Los geht's</button></Fragment> : <Frontpage /> }
</div>
</header>
</div>
);
}
}
export default App;
You have to bind the handleClick to your class component or in other case, use an arrow function:
To bind the method at the bottom of your state inside the constructor add this :
this.handleClick = this.handleClick.bind(this);
To use the arrow function change the syntax of your method as:
this.handleClick = () => {
if (this.state.showComponent) {
return <Question />
} else {
console.log("Something went wrong!")
}
}
import React from 'react';
import './App.css';
import Frontpage from './Frontpage'
import Question from './components/Question'
class App extends React.Component {
constructor() {
super()
// Start with a hide component
this.state = {
showComponent: false,
}
// Binding your function
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
const { showComponent } = this.state;
// Use state to trigger a re-render
this.setState({
showComponent: !showComponent;
})
}
render() {
const { showComponent } = this.state;
return (
<div className="App">
<header className="App-header">
<div id="page">
{
// Conditionally render a component
showComponent
? (<Question />)
: (<Frontpage />)
}
</div>
<button id="button" onClick={this.handleClick}>Los get's</button>
</header>
</div>
);
}
}
export default App;
Try this one.
import Question from './components/Question'
class App extends React.Component {
constructor() {
super()
this.state = {
showComponent: true,
}
}
handleClick() {
this.setState({ showComponent: true });
}
render() {
const { showComponent } = this.state;
return (
<div className="App">
<header className="App-header">
<div id="page">
<Frontpage />
</div>
{ showComponent ? <Question /> : null }
<button id="button" onClick={this.handleClick.bind(this)}>Los geht's</button>
</header>
</div>
);
}
}
export default App;

How do I close upon button click of a rendered component in react?

I'm having trouble figuring out how to close a component that's rendered. I currently have am able to open the modal component on my first page, but then I want to close it upon the click of a button through the component. How would I do that?
import React, { Component } from 'react';
import AddModal from './addmodal';
class Page extends Component {
constructor(){
super();
this.state = { isModalOpen: false };
}
...//skip
handleAdd= () =>{
this.setState({ isModalOpen: true });
}
render(){
return (
<div>
<button onClick={this.handleAdd} > Add </button>
<AddModal isOpen={this.state.isModalOpen} />
</div>
)
}
}
import React, { Component } from 'react';
class AddModal extends Component {
// ... skip
handleClose = () => {
this.setState({ open: false });
};
render(){
return(
<modal inOpen={this.props.isOpen} >
<Button onClick={this.handleClose}>
Okay
</Button>
...//skip
</modal>
)
}
}
export default AddModal;
You need to make your modal component call an onClose callback so the parent can close it:
import React, { Component } from 'react';
import AddModal from './addmodal';
class Page extends Component {
constructor(){
super();
this.state = { isModalOpen: false };
}
...//skip
handleAdd= () =>{
this.setState({ isModalOpen: true });
}
handleClose= () =>{
this.setState({ isModalOpen: false });
}
render(){
return (
<div>
<button onClick={this.handleAdd} > Add </button>
<AddModal isOpen={this.state.isModalOpen} handleClose={this.handleClose}/>
</div>
)
}
}
import React, { Component } from 'react';
class AddModal extends Component {
// ... skip
render(){
return(
<modal inOpen={this.props.isOpen} >
<Button onClick={this.props.handleClose}> // call to parent
Okay
</Button>
...//skip
</modal>
)
}
}
export default AddModal;
The parent component will decide whether the modal is open or not, hence it owns the state of the child.
Building on what #jsdeveloper posted, I think you can cut the clutter by using the same function to handle the opening and closing of the modal.
We will make use of a toggleModal function which changes the isModalOpen to true when it's false and vice versa. It uses a callback, which takes in the previous state value of isModalOpen.
toggleModal = () => {
this.setState(prevState => ({
isModalOpen: !prevState.isModalOpen
}))
}
So the final file should look something like this.
import React, { Component } from 'react';
import AddModal from './addmodal';
class Page extends Component {
constructor() {
super();
this.state = {
isModalOpen: false
};
}
// ... //skip
toggleModal = () => {
this.setState((prevState) => ({
isModalOpen: !prevState.isModalOpen
}));
};
render() {
return (
<div>
<button onClick={this.handleAdd}> Add </button>{' '}
<AddModal
isOpen={this.state.isModalOpen}
toggleModal={this.toggleModal}
/>
</div>
);
}
}
import React, { Component } from 'react';
class AddModal extends Component {
// ... skip
render() {
return (
<modal inOpen={this.props.isOpen}>
<Button onClick={this.props.toggleModal}>Close</Button>
//... skip
</modal>
);
}
}
export default AddModal;

Categories

Resources