I'm displaying a overlay page when a certain input is clicked. Now I want to remove that overlay page when a user clicks somewhere in that overlay. How can I do that?
I'm displaying the overlay on click like this
constructor(props) {
super(props);
this.state = {
showComponent: false,
};
this.popup_ques = this.popup_ques.bind(this);
}
popup_ques() {
this.setState({
showComponent: true,
});
}
render() {
return (
<div className="ff">
<div className="middle_div">
<input className='post_data_input' placeholder="Ask your question here" ref="postTxt" onClick={this.popup_ques}/>
</div>
{this.state.showComponent ? <QuestionOverlay/> : null}
</div>
);
}
My overlay is in the component QuestionOverlay
class QuestionOverlay extends Component {
constructor() {
super();
}
closeOverLay = (e) => {
alert("fse");
}
render() {
return (
//Here I have implemented my overlay
)
}
}
export default QuestionOverlay;
So how can I close/remove the overlay component when I click somewhere on my overlay?
Pass a function from the Overlay's parent component (the component which displays the Overlay) that is called onClick in the Overlay. This function will update this.state.showComponent of the parent to false to hide the Overlay.
Parent
constructor(props) {
super(props);
this.state = {
showComponent: false,
};
this.popup_ques = this.popup_ques.bind(this);
this.hide_overlay = this.hide_overlay.bind(this);
}
popup_ques() {
this.setState({
showComponent: true,
});
}
hide_overlay() {
this.setState({
showComponent: false
})
}
render() {
return (
<div className="ff">
<div className="middle_div">
<input className='post_data_input' placeholder="Ask your question here" ref="postTxt" onClick={this.popup_ques}/>
</div>
{this.state.showComponent && <QuestionOverlay hideOverlay={this.hide_overlay} />}
</div>
);
}
Overlay
class QuestionOverlay extends Component {
constructor() {
super();
}
closeOverLay = (e) => {
alert("fse");
}
render() {
return (
<div onClick={this.props.hideOverlay}>
// Overlay content
</div>
)
}
}
export default QuestionOverlay;
Related
So I am quite new to React world, and I have this problem I am trying to solve, but I don't quite understand why it is happening.
So I want to pass the state of component to parent component and from parent component to child component and everything look okay, and in console log the state goes trough, but nothing changes. I believe there is a way I need to listen for state change or something within child component so it works. If I put true in the parent component, child component also get's true, but if I toggle it on click, it goes trough but nothing changes in the child component.
Also I understand my code is little rough right now ill reafactor it later, but right now I am trying to understand why it does not work.
If anyone could help me I would be thankful for it.
This is component that controls the state.. So the state passes from TurnOnBtn to App and from App it goes to TodoList
import "./Todo.css";
class TurnOnBtn extends Component {
constructor(props) {
super(props);
this.state = { display: false };
this.handleState = this.handleState.bind(this);
}
handleState() {
this.setState({ display: !this.state.display });
this.props.checkDisplay(this.state.display);
}
render() {
return (
<button onClick={this.handleState} className="TurnOnBtn">
<i className="fa fa-power-off"></i>
</button>
);
}
}
export default TurnOnBtn;
parent component App
import TurnOnBtn from "./TurnOnBtn";
import TheMatrix from "./TheMatrxHasYou";
import TodoList from "./TodoList";
import { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = { display: true };
this.checkDisplay = this.checkDisplay.bind(this);
}
checkDisplay(newDisplay) {
this.setState({
display: newDisplay,
});
console.log(this.state);
}
render() {
return (
<div className="App">
<TodoList display={this.state.display} />
<TheMatrix />
<TurnOnBtn checkDisplay={this.checkDisplay} />
</div>
);
}
}
export default App;
child component TodoList
import Todo from "./Todo";
import NewTodoForm from "./NewTodoForm";
import { v4 as uuid } from "uuid";
import "./Todo.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
displayOn: this.props.display,
};
this.newTodo = this.newTodo.bind(this);
this.editTodo = this.editTodo.bind(this);
this.deleteTodo = this.deleteTodo.bind(this);
}
editTodo(id, updatedTask) {
const updatedTodo = this.state.todos.map((todo) => {
if (todo.id === id) {
return { ...todo, todo: updatedTask };
}
return todo;
});
this.setState({
todos: updatedTodo,
});
console.log(updatedTask);
}
deleteTodo(id) {
this.setState({
todos: this.state.todos.filter((todo) => todo.id !== id),
});
}
newTodo(newState) {
this.setState({
todos: [...this.state.todos, { ...newState }],
});
}
render() {
return (
<div
style={this.state.displayOn ? { opacity: 1 } : { opacity: 0 }}
className="Todo-screen"
>
{" "}
<div className="TodoList">
<div className="TodoList-todos">
{" "}
{this.state.todos.map((todo) => (
<Todo
key={uuid()}
id={todo.id}
active={todo.active}
editTodo={this.editTodo}
deleteTodo={this.deleteTodo}
todoItem={todo.todo}
/>
))}
</div>
</div>{" "}
<NewTodoForm newTodo={this.newTodo} />
</div>
);
}
}
export default TodoList;
The bug here is in these line of codes:
handleState() {
this.setState({ display: !this.state.display });
this.props.checkDisplay(this.state.display);
}
Remember setState is an async function, so by the time you set a new state using setState, the value for this.state is not guaranteed changed.
One way to fix this is using the setState callback, which will run after the state is changed:
handleState() {
this.setState({ display: !this.state.display }, function() {
this.props.checkDisplay(this.state.display);
});
}
But you don't need to use another state to keep display state in TurnOnBtn as you can pass the toggle callback from the parent:
App.js
class App extends Component {
constructor(props) {
super(props);
this.state = { display: true };
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display,
});
}
render() {
return (
<div className="App">
<TodoList display={this.state.display} />
<TheMatrix />
<TurnOnBtn toggleDisplay={this.toggleDisplay} />
</div>
);
}
}
TurnOnBtn.js
class TurnOnBtn extends Component {
constructor(props) {
super(props);
this.handleState = this.handleState.bind(this);
}
handleState() {
this.props.toggleDisplay();
}
render() {
return (
<button onClick={this.handleState} className="TurnOnBtn">
<i className="fa fa-power-off"></i>
</button>
);
}
}
I want access properties like id, etc of the clicked item on the modal. How can I pass target properties as props to modal on click.
Below is what I am trying. Unfortunately, the modal shows the targetElement prop as undefined in componentDidMount function of CropperModal
export default class DynamicArticleList extends React.Component {
constructor(){
super();
this.state={
targetElement: '',
}
this.showModal = this.showModal.bind(this);
this.hideModal = this.hideModal.bind(this);
}
showModal(e){
this.setState({
targetElement: e.target.getAttribute("id")
})
}
hideModal(e){
this.setState({
showing: false,
showSource: '#',
})
}
render() {
return (
<div className="wrapper container-fluid DynamicArticleList">
<div className="width-control">
<img src="../img/journey.jpg" onDoubleClick={this.showModal} id="Img0"/>
<CropperModal targetElement={this.state.targetElement}/>
</div>
</div>
);
}
}
Here's how I did it. I basically avoided the modal component to render until the click event was processed
export default class DynamicArticleList extends React.Component {
constructor(){
super();
this.state={
showing: false,
targetElement: '',
}
this.showModal = this.showModal.bind(this);
this.hideModal = this.hideModal.bind(this);
}
showModal(e){
this.setState({
showing: true,
targetElement: e.target.getAttribute("id")
})
}
hideModal(e){
this.setState({
showing: false,
showSource: '#',
})
}
render() {
return (
<div className="wrapper container-fluid DynamicArticleList">
<div className="width-control">
<img src="../img/journey.jpg" onDoubleClick={this.showModal} id="Img0"/>
{this.state.showing ? <CropperModal targetElement={this.state.targetElement}/> : null}
</div>
</div>
);
}
}
I have two child components. The first child is an image and the second child is a search input. When I type something in the input field, I want the image to hide itself. The passing of data from the second child to the parent goes well. But the first child still appears...
Parent:
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image />
<Search hideImage={this.hideImage()}/>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('root'));
First Child:
export default class Image extends Component {
render() {
return (
<div>
<img style={{display : this.props.displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
)
}
}
Second Child:
export default class Search extends Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting"></input>
</div>
)
}
}
You have to pass the displayValue state into your Image component as a prop. Also you have to pass the hideImage function without initializing it using the two brackets. The below code should work for you.
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: 'block'
};
}
hideImage = () => () => {
alert('You pressed a key, now the apple should be gone')
this.setState ({
displayValue: 'none'
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage}/>
</div>
);
}
}
You just had a couple of typos.
class Image extends React.Component {
render() {
return (
<div>
<img
style={{ display: this.props.displayValue }}
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"
alt="altprop"
/>
</div>
);
}
}
// Second Child:
class Search extends React.Component {
render() {
return (
<div>
<input onInput={this.props.hideImage} placeholder="Search someting" />
</div>
);
}
}
class Main extends React.Component {
constructor() {
super();
this.state = {
displayValue: "block"
};
}
hideImage(e) {
e.preventDefault();
alert("You pressed a key, now the apple should be gone");
this.setState({
displayValue: "none"
});
};
render() {
return (
<div>
<Image displayValue={this.state.displayValue}/>
<Search hideImage={this.hideImage.bind(this)} />
</div>
);
}
}
Call your Image component like this
<Image displayValue={this.state.displayValue} />
It should then already work, but here is a shorter way to write your code.
// First Child:
const Image = ({displayValue}) => <div>
<img alt='' style={{display : displayValue}} src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTAxoq2YSBjoS0Lo3-zfqghoyNzZ9jHxoOc5xuFBoopMtKP6n4B"></img>
</div>
I want to toggleclass name of one element by clicking on another element. Both elements are in separate component files. I don't know how to get the state of an element and pass it to another element. Please help me solving the problem.
file1.js
<Button onClick={this.toggleFunction}>Button</Button>
file2.js
<div class="wrapper"></div>
I want to toggle class active on wrapper div when the button is clicked.
Thanks
class MyComponent extends Component {
constructor(props) {
super(props);
this.addActiveClass= this.addActiveClass.bind(this);
this.state = {
active: false,
};
}
toggleClass() {
const currentState = this.state.active;
this.setState({ active: !currentState });
};
render() {
return (
<div
className={this.state.active ? 'your_className': null}
onClick={this.toggleClass}
>
<p>{this.props.text}</p>
</div>
)
}
}
Parent Component
import React from "react";
import ButtonComponent from "./buttonComponent";
import "./demo.css";
//Parent Component
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
active: false
};
}
updateValue = value => {
this.setState({
active: value
});
};
render() {
return (
<div>
<ButtonComponent updateParent={this.updateValue} />
<div
className={
this.state.active ? "dropdownbutton1" : "dropdownbutton1Active"
}
>
<label>First</label>
<br />
<select>
<option value="yes">yes</option>
<option value="no">no</option>
</select>
</div>
</div>
);
}
}
export default Demo;
Child Component
import React from "react";
import ToggleButton from "react-toggle-button";
import "./demo.css";
class ButtonComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
active: false,
defaultValue: 1
};
}
togglebutton = () => {
this.props.updateParent(this.state.active);
this.setState({ active: !this.state.active });
if (this.state.active) {
this.setState({ defaultValue: 1 });
} else {
this.setState({ defaultValue: -1 });
}
};
render() {
return (
<div>
<div className="ToggleButton">
<ToggleButton onClick={this.togglebutton} value={this.state.active} />
</div>
</div>
);
}
}
export default ButtonComponent;
Link :https://codesandbox.io/s/m4py2y97zp
I have this code:
class ItemWrap extends Component {
constructor() {
super();
this.state = { showItem: true};
this.removeItem = this.removeItem.bind(this);
}
removeItem() {
this.setState({ showItem: false });
}
render() {
var item = this.state.showItem ? <Item data_items={this.props.data_items} /> : '';
return (
<div id="sss">
{item}
<button onClick={this.removeItem}>remove image</button>
</div>
);
}
}
export default ItemWrap;
On button click I remove {item}. But the button is stay. I need to remove all ItemWrap after button click.
Help me )
Firstly,removeItem function is designed for change flag of state,
and then you can use this flag to veiw whatever you want.
ex:
if(flag)
return (your current div);
else
return(
whatever you want , empty or other
)
The rendering should be managed in the parent component, here is a possible solution
class ItemWrap extends Component {
constructor() {
super();
}
render() {
return (
<div id="sss">
<Item data_items={this.props.data_items} />
<button onClick={this.props.onClickBtn}>remove image</button>
</div>
);
}
}
export default ItemWrap;
then in the wrapper you can manage the rendering of ItemWrap
class Wrapper extends Component {
constructor() {
super();
this.state = { showItem: true};
this.removeItem= this.removeItem.bind(this);
}
removeItem() {
this.setState({ showItem: false });
}
render() {
return (
<div>
{ this.state.showItem && <ItemWrapper onClickBtn={this.removeItem} /> }
</div>
);
}
}
export default Wrapper;