Clicking the button does not work - React - reactjs

I use a component called "Modal" that I want to make global so I can use it in any other component. Modal will be used in all the components that need it.
My problem is that now the onclick {this.props.stateModal} in Widgets does not work and show nothing.
This is my Widgets.js
class Widgets extends Component {
render(){
return (
<aside className="widgets">
<div id="bq-datos">
<span>Todas tus campañas</span>
<a onClick={this.props.stateModal} className="content-datos orange" data-bq-datos="999"><div>Llamadas <span>ENTRANTES</span></div></a>
<a className="content-datos violet" data-bq-datos="854"><div>Llamadas <span>SALIENTES</span></div></a>
</div>
{
this.props.isModalOpen
? (
<Modal
stateModal = {this.props.stateModal}
isModalOpen={this.props.isModalOpen} >
<ModalWidgets/>
</Modal>
)
: null
}
<Comunicacion/>
</aside>
);
}
}
I need {this.props.stateModal} to work on my Modal component (in Modal.js)
This is my Modal.js with code for {this.props.stateModal} but not works.
import React, { Component } from 'react';
class Modal extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false,
};
this.stateModal = this.stateModal.bind(this);
}
stateModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
alert('¡Ohhhh');
}
render(){
if(this.props.isOpen){
return (
<div id="modal">
{this.props.children}
<ModalWidgets/>
</div>
);
} else {
return null;
}
}
}
class ModalWidgets extends Component {
render(){
if(this.props.isModalOpen){
return(
<article id="md-descansos" className="medium">
hola tú!!
</article>
);
}
else{
return(
<div>k pasa!</div>
);
}
}
}
export default Modal;
I think that i need do something in my Modal.js but i don't know what it is
Edit:
I have changed the components to use Modal as the parent of all the other Modal that I want to use, such as ModalWidgets. But now when you click on the button of {this.props.stateModal} in Widgts not works.
Thanks!

You have to use stateModal function somewhere in your Modal component. Something like:
render(){
if(this.props.isOpen){
return (
<ModalGenerico>
<div id="modal">
<button type="button" onClick={this.stateModal}>Click here</button>
{this.props.children}
</div>
</ModalGenerico>
);
} else {
return <ModalGenerico />;
}
}
The button in the example above should be replaced with your backdrop of the modal (or anything else as you like).
Edited: You should take a look at this article State vs Props. Because I notice that you weren't clear the usage of them.
Besides, I don't think there's such thing called global component as you described. Every components in react are reusable and can be imported anywhere in the project.

Related

I want a simple button to display text. Why is this not working?

The app works, but when I click the button nothing happens. I'm experimenting with buttons and I at least want to get a button to be able to affect the markup on the page.
class Add extends Component {
state = { }
clickme(){
<h2>hello</h2>
}
render() {
return (
<>
<Title />
<button type="button" onClick={this.clickme}>Add task</button>
</>
);
}
}
export default Add;
Your function is not returning anything. You can use state and use clickme to update the state when the button is clicked
class Add extends Component {
state = { waiting:true, title:"" }
clickme(){
this.setState({ title: "Hello", waiting : false});
}
render() {
return (
<>
<h2>{this.state.waiting?"Waiting For Click...":this.state.title}</h2>
<button type="button" onClick={this.clickme}>Add task</button>
</>
);
}
}
export default Add;
You need to return the component from the function. Either turn clickme() into an arrow function, which implicitly returns, or add a return statement (might have to wrap it in some brackets, not sure).
Also, where do you expect the "hello" to render exactly?
P.S. Have you tried using functional instead of class components? That's been the recommended approach by the React team and community for a few years now.
class Add extends Component {
state = { }
clickme(){
return <h2>hello</h2>;
}
render() {
return (
<>
<Title />
<button type="button" onClick={this.clickme}>Add task</button>
</>
);
}
}
export default Add;

Why I can't use an imported component inside a functional component in React?

I am new to React. For the code readability, instead of in-line styled button, I want to write it as a separate class component. I created a customed button 'addImageButton'and imported it to another .js file. It doesn't render the customer button when I try to use it within a functional component. How can I make the functional component be able to use the imported button? Thanks!
//addImageButton.js
import React, { Component } from "react";
class addImageButton extends Component {
render() {
return (
<div>
<button
style={{
borderStyle: "dotted",
borderRadius: 1,
}}
>
<span>Add Image</span>
<span>Optional</span>
</button>
</div>
);
}
}
export default addImageButton;
//AddNewTaskButton.js
import React, { Component } from "react";
import Modal from "react-modal";
**import addImageButton from "../addImageButton";**
class AddNewTaskButton extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
};
this.setShow = this.setShow.bind(this);
this.closeShow = this.closeShow.bind(this);
this.addTaskModal = this.addTaskModal.bind(this);
}
setShow() {
this.setState({
show: true,
});
}
closeShow() {
this.setState({
show: false,
});
}
addTaskModal = () => {
return (
<div>
<Modal
isOpen={this.state.show}
onRequestClose={() => this.closeShow()}
>
**<addImageButton />**
</Modal>
</div>
);
};
render() {
return (
<div>
<button onClick={() => this.setShow()}>
<img src={addIcon} alt={text}></img>;
<span>text</span>
</button>
<this.addTaskModal className="modal" />
</div>
);
}
}
export default AddNewTaskButton;
Easier way would be to just use functional components. Also, react components should be upper case, like so:
export default function AddImageButton() {
return (
<div>...</div>
)
}
create a different component for Modal
import Modal from './Modal'
import AddImageButton from './AddImageButton'
function AddTaskModal() {
return (
<div>
<Modal> <AddImageButton/> </Modal>
</div>
)
}
then
import AddTaskModal from './AddTaskModal'
function AddNewTaskButton() {
return (
<div>
<AddTaskModal/>
</div>
)
}
I don't know your file directories, so I just put randomly.
as for your question, try to make the AddImageButton as a class and see if it renders then. If it doesn't it might be due to something else. Do you get errors? Also maybe create the AddTaskModal class separately and render it out as a component. Maybe that'll help

Cannot pass a simplified function to onClick event handler ReactJs

In my React app, I have two Components, Main and Menu Component. Main Component is the parent component of Menu. Menu shows a list of items and upon clicking one of the item, it updates Main's state with the help of a function that I pass as props to Menu. Below is the code for better understanding:
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
dishes: dishes,
selectedDish: null
};
this.selectDish=this.selectDish.bind(this);
}
selectDish(dishId){
this.setState({ selectedDish: dishId});
}
render() {
return (
<div className="App">
<Menu dishes={this.state.dishes} onClick={this.selectDish} />
</div>
);
}
}
export default Main;
And below is the Menu Component:
class Menu extends Component {
constructor(props){
super(props);
this.selectdish=this.selectdish.bind(this);
}
selectdish(dishId){
return this.props.onClick(dishId);
}
render() {
const menu = this.props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1">
<Card key={dish.id}
onClick={this.selectdish(dish.id)}>
</Card>
</div>
);
});
}
}
export default Menu;
I have omissed some irrelevant parts of the code.
So the workflow should be that when we click over one of dishes rendered by the Menu, that dish's id should be passed back to Main and update the state variable ```selectedDish````, as seen in the method selectDish.
But in the browser console, I get the error Cannot update during existing state transition.
The weird thing is that if I don't pass any dish id and set the selectedDish to a fixed value like 1, everything works fine.
Please help me guys to identify if there is any problem in my event handler, because that is the only part that seems to contain an error.
Thank You!
You are not passing the onClick of the Card a function but you are already calling that function with this.selectdish(dish.id). This will initiate the flow on render, not on click.
You have three options here.
You either wrap that in an additional function like this: onClick={() => {this.selectdish(dish.id)}}>. That way, you are passing a function to the onClick, which is required, and not executing that.
Or you make selectdish return a function like this:
selectdish(dishId){
return () => {this.props.onClick(dishId)};
}
Or you add a name to the card and access the name of the element from the click event:
class Menu extends Component {
constructor(props){
super(props);
this.selectdish=this.selectdish.bind(this);
}
selectdish(event){
return this.props.onClick(event.target.name);
}
render() {
const menu = this.props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1">
<Card key={dish.id}
name={dish.id}
onClick={this.selectdish}> // this is now the function without calling it
</Card>
</div>
);
});
}
}
export default Menu;
You have some problem in your code:
property key must be define in root <div>
render method in Menu component returns nothing
-
class Menu extends React.Component {
constructor(props) {
super(props);
this.selectdish = this.selectdish.bind(this);
}
selectdish(dishId) {
return this.props.onClick(dishId);
}
render() {
return this.props.dishes.map(dish => {
return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<div onClick={() => this.selectdish(dish.id)}>{dish.id}</div>
</div>
);
});
}
}
See my playground where I fixed this issues:
https://codesandbox.io/s/react-playground-ib6pr?file=/index.js

simplest approach of dynamically adding components in react

currently working on react. I have two components lets say ad and home . Inside home components i have one image and on click event of that image i want to render ad inside home component below image. Is there any simples method . thank you!
check this. i think this is what you want
//dynamically generate div
let DynamicDiv=()=>{
return (<div>
<p>i am here</p>
</div>)
}
class App extends Component {
constructor(props){
super(props)
this.state={
visible:false //visibility of Component
}
this.divVisiblity=this.divVisiblity.bind(this) //function is bind when user clicks on pic
}
divVisiblity(){
//this function will get called when user clicks on function
this.setState(()=>{return {visible:!this.state.visible}}) //changes visible state of Component when user clicks
}
render() {
return (
<div>
<div className="App">
{/* onClick is assigned function named divVisiblity */}
<img onClick={this.divVisiblity} src="https://placekitten.com/g/200/300" alt="test"/>
{/*this is ternary if else statement in js */}
{/* if visible = true ,display Component else dont */}
<div>
{this.state.visible && <DynamicDiv/>}
</div>
);
}
}
I think that will help to you.
export default class HomeComponent extends Component<Props> {
constructor(props) {
super(props);
this.state = {
renderAdComponent: false
};
this.onClickHandler = this.onClickHandler.bind(this);
}
onClickHandler() {
this.setState({renderAdComponent: !this.state.renderAdComponent})
}
render() {
return (
<View>
<Image onClick={this.onClickHandler}/>
{this.state.renderAdComponent ? <AdComponent/> : null}
</View>
);
}
}
What #sdkcy suggested is okay but the ternary operator isn't really needed. You can do the following
{ this.state.isAdShown && <ComponentToShow /> }
This gets rid of the useless : null result.

Custom React-Bootstrap Popover

I want to create a custom react popover, based on Bootstrap Popover, just with my own design and maybe more props.
I created a new react component called MyTooltip :
import React, {Component} from 'react';
import { Popover } from 'react-bootstrap';
export default class MyPopover extends Component{
constructor(props){
super(props);
}
render() {
return (
<Popover id="popover-trigger-focus" title={this.props.title}>
{ return this.props.children }
</Popover>
);
}
}
and in my main component I tried to create a trigger:
export default class MyMainComponent extends Component{
render() {
const popoverFocus = (
<MyPopover id="tooltip-trigger-focus" title="My Title">
my text <b>my bold text</b> my text
</MyPopover >
);
return (
<div >
<OverlayTrigger trigger="focus" placement="bottom" overlay={popoverFocus}>
<Button>Focus</Button>
</OverlayTrigger>
</div>
);
}
}
But it doesn't work. The button does hide and show the popover with the right text, but the popover ignores the "placement" property and it doesn't have the fade animation.
Any help will be useful...
You've set the placement and overlay prop to the <OverlayTrigger/> element, but those belong on the Popover. You can quickly fix this by letting the popover inherit the props from the trigger element like so:
render() {
return (
<Popover id="popover-trigger-focus" title={this.props.title} {...this.props}>
{ this.props.children }
</Popover>
);
}
Here's your example with {...this.props}.
PS: You don't need to return JS in JSX (e.g. { return this.props.children }). You can just leave that out ({ this.props.children }).

Resources