React render not changing when calling from Button - reactjs

When I click the login or register button in the following react code, the renderView() function is not rendering the Login(or the Register) component on the page.
When I log the value of e.currentTarget.value in the console, the correct values are getting logged when the button is clicked.
How do I fix this?
I want the corresponding components to be displayed when I click the Login or Register Buttons
const AppHomePage = () => {
const classes = useStyles();
const [renderVal, setRenderVal] = useState(0);
const renderView = () => {
switch(renderVal){
case 0:
return <Page />
case 1:
return <Register />
case 2:
return <Login />
default:
return <Page />
}
}
const ButtonChange = (e) => {
setRenderVal(e.currentTarget.value);
}
return(
<div>
<AppBar className={classes.root} position='static' >
<Toolbar className={classes.appbar}>
<Button className={classes.buttons} value={1} variant="contained" color="primary" onClick={ButtonChange}>
Register
</Button>
<Button className={classes.buttons} value={2} variant="contained" color="primary" onClick={ButtonChange}>
Login
</Button>
</Toolbar>
</AppBar>
<div>
{ renderView() }
</div>
<CssBaseline />
</div>
)
}
const Login = () => {
return(
<div>
<p>login</p>
</div>
)
}
const Register = () => {
return(
<div>
register
</div>
)
}
const Page = () => {
return(
<div>
page
</div>
)
}

Pass the value inside onClick function. Use an arrow function and pass the id like 1 or 2. onClick={() => ButtonChange(1)}
<Button className={classes.buttons} variant="contained" color="primary" onClick={() => ButtonChange(1)}>
Register
</Button>
<Button className={classes.buttons} variant="contained" color="primary" onClick={()=>ButtonChange(2)}>
Login
</Button>
Now in ButtonChange function get the value passed in previous step.
const ButtonChange = (id) => {
setRenderVal(id);
}

I fixed it by simply changing the cases from case 1: to case '1': and so on...

Related

Passing click function from One component to other component

In React material ui i am having two components where i am calling save function on button click, is it right way or not can anyone suggest the better way:
const callback = {};
return (
<>
{!state?.creditCard?.isSaved ? (
<Paper elevation={4} className={classes.paymentContainer}>
<Box className={classes.subPaymentContainer}>
<Typography className={classes.title}>Card Payment</Typography>
<CardPaymentForm
callback={callback}
validationPassed={() => actionsCollection.booking.saveCard(true, state.creditCard.lastFourDigits)}
formType="profileForm"
/>
<div>
<Button
type="submit"
onClick={(e) => callback.saveCard(e)}
value="SAVE CREDIT CARD"
className={classes.button}
/>
<div style={{ display: "flex", marginTop: 20 }}>
<img className={classes.lockIcon} src={lockIconInfo} alt="" />
<Typography className={classes.paymentInfo}>
<Link href="/terms" target={"_blank"}>
Terms of Payment
</Link>
.
</Typography>
</div>
</div>
</Box>
</Paper>
) : (
<div style={{ height: 373 }}>
<CardStored removeCard={removeCard} />
</div>
)}
</>
);
in CardPayementForm below calling the save function below is the code:
const CardPaymentForm = ({ classes, callback, validationPassed, formType, lastFourDigits }) {
useEffect(() => {
callback.saveCard = (e) => {
e.preventDefault();
=
if (validateForm()) {
=
validationPassed();
}
};
});
}
here without callback how to call save function directly in cardpaymentform, Any help please
I'm not sure this will apply to your problem but if you had a component_a
like
const ComponentA = ({handleClick}) => {
return(
<>
<button onClick(e => handleEvent(e))>
Click here
</button>
</>
}
and a component_b
const ComponentB = () => {
const handleClick = (e) => {
// do something with the event from component a
}
return(
<>
<ComponentA handleClick={handleClick}/>
</>
)
}

Passing function to another component getting error this is not defined react js

I am developing an app with sliding menu in react but I am getting the following error.
this is not defined
My code
Myfile
const toggleMenu = () => {
alert("clicked");
state = !state
if (state === false) {
const visibllity = "close";
alert("open")
} else {
const viisibility = "open"
alert("close")
}
}
return (
<RiderHeader toggleMenu={this.toggleMenu()} />
)
RiderHeader.js
return (
<div className="user-header">
<IconButton onClick={() => toggleMenu()}>
<MenuIcon />
</IconButton>
</div>
)
thisYou shouldn't call the function when you are declaring (or passing it as a prop).
<Component prop={this.func} /> or <Component prop={() => this.func()} />
In you file where toggleMenu is defined,
return (
<RiderHeader toggleMenu={this.toggleMenu} />
)
In RiderHeader.js,
If it's a class component then,
return (
<div className="user-header">
<IconButton onClick={() => this.props.toggleMenu()}>
{/* or
<IconButton onClick={this.props.toggleMenu}>
*/}
<MenuIcon />
</IconButton>
</div>
)
If it's a functional component,
return (
<div className="user-header">
<IconButton onClick={() => props.toggleMenu()}>
{/* or
<IconButton onClick={props.toggleMenu}>
*/}
<MenuIcon />
</IconButton>
</div>
)

How can i call a function inside another Component with React?

I have a component (Navigation.js) which imports another component (Dialog.js). I want that if I react to a click event, call a function in the dialog component (handleClickOpen ()). But I don't know how to do that. So what i have to do ?
Navigation.js
export default function SimpleBottomNavigation() {
return (
<BottomNavigation
value={value}
onChange={(event, newValue) => {
setValue(newValue);
}}
showLabels
className={classes.root}
>
<BottomNavigationAction
label="Home"
onClick={'HERE I WANT TO CALL THE FUNCTION IN THE DIALOG COMPONENT'}
icon={<RestoreIcon />}
/>
<BottomNavigationAction label="Neuer Plan" icon={<FavoriteIcon />} />
<BottomNavigationAction label="Azubis" icon={<LocationOnIcon />} />
</BottomNavigation>
);
}
Dialog.js
export default function CustomizedDialogs() {
const [open, setOpen] = React.useState(false);
*/THIS FUNCTION I WANT TO CALL FROM NAVIGATION.JS */
const handleClickOpen = () => {
setOpen(true);
};
[...]
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open dialog
</Button>
<Dialog
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
Modal title
</DialogTitle>
<DialogContent dividers>
</Dialog>
</div>
);
}
There is a aimple way to use child's functions, with functional components it's forwardRef and useImperativeHandle, along those lines:
Navigation (parent)
function Navigation() {
const dialogRef = useRef();
return(
<button onClick={() => dialogRef.current.handleClickOpen()}>
Click me!
</button>
);
}
Dialog (child)
const Dialog = forwardRef((props, ref) => {
useImperativeHandle(ref, () => {
const handleClickOpen = () => {
//your implementation
};
});
return (...);
});
If I over-simplified, please let me know :)

React - how to invoke popup window in my case?

I'm not a React expert yet thus I have a question for you - how to invoke my popup window from:
import {options, columns,convertToArray} from './consts'
const index = () => {
const {data, loading, error, performFetch} = fetchHook({path: "/xxx/yyy", fetchOnMount: true})
return (
<div className={classes.Container}>
<h1>List of products</h1>
<Divider className={classes.Divider} />
<ProductTable data={convertToArray(data)} options={options} columns={columns}/>
</div>
)
}
export default index;
consts.js
export const actions = (productPropertyId, showModal) => {
const productDetails = (productPropertyId) => {
}
const removeProduct = (productPropertyId, showModal) => {
actions(productPropertyId, showModal);
return (
<div className={classes.actionsContainer}>
<Button
onClick={() => productDetails(productPropertyId)}
> {"More"}
</Button>
<Button
const removeProduct = (productPropertyId, showModal) => {
actions(productPropertyId, showModal);
>{"Remove"}
</Button>
</div>
)
};
export const convertToArray = (productList) => {
let products = []
if (productList != null) {
productList.map(product => {
column1, column2, column3, actions(product.id)]
products.push(prod)
})
}
return products;
};
My popup is --> <FormDialog/> based on react Materials.
Is it possible to invoke popup in this place?
I have a react material table with some columns. The last column contains 2 buttons, one of them is "Remove" (row). Here I want to invoke my popup. Maybe I should rebuild my structure?
UPDATE
Below is my popup - I wonder how to run this popup from the place above:
const formDialog = (popupOpen) => {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
{/*<Button variant="outlined" color="primary" onClick={handleClickOpen}>*/}
{/* Open alert dialog*/}
{/*</Button>*/}
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send updates
occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Subscribe
</Button>
</DialogActions>
</Dialog>
</div>
);
}
export default formDialog;
UPDATE 2
I updated my code taking into cosideration the tips from your response, see above. Can I add a parameter showModal in my export const actions = (productPropertyId, showModal) and then invoke this component with different showModal value? UNfortunately my popup doesn't appear when I click on Remove button :(
You can invoke it conditionally and controle it using some state variable. Like this:
const [removeModal, removeToggle] = useState(false);
return (<>
<div className={classes.actionsContainer}>
<Button
onClick={() => productDetails(productPropertyId)}
> {"More"}
</Button>
<Button
onClick={() => removeToggle(true)}
>{"Remove"}
</Button>
</div>
{removeModal ? <YourComponent /> : ''}
</>
)
I'm using a react fragment there <></> just to position the modal div outside the main div, but you can also invoke it inside your main div as well (I usually do this and set the position: fixed so the modal/popup coud appear in top of everything).

Child component list not rendering

I am trying to render a list using a child component and it ends up not rendering anything.
Snippet in PropertyBar component:
updateSelectedCell() {
if (graph.selectedCell != null) {
this.setState({
selectedCell: graph.selectedCell,
cellProperties: Array.from(graph.selectedCell.value.attributes)
});
}
}
renderPropertyList() {
this.state.cellProperties.map(key => {
<PropertyBarItem name={key.nodeName} value={key.nodeValue} />
})
}
render() {
if (this.state.selectedCell != null) {
return (
<div>
<Button variant="contained" color="primary" fullWidth={true} onClick={() => this.updateSelectedCell()}> View properties </Button>
<List>
{this.renderPropertyList}
</List>
</div>
)
}
return (
<div>
<Button variant="contained" color="primary" fullWidth={true} onClick={() => this.updateSelectedCell()}> View properties </Button>
<List>
<p>Click on a cell to view its properties.</p>
</List>
</div>
)
}
When a user clicks on the button, it updates the state with an array then should render a list of PropertyBarItem with the keys inside the array. It ends up not displaying anything, but doesn't crash. Testing using a simple p tag and it also does not render anything:
renderPropertyList() {
this.state.cellProperties.map(key => {
<p> {key} </p>
})
}
You are not invoking the renderPropertyList method. Add () to invoke it.
<div>
<Button
variant="contained"
color="primary"
fullWidth={true}
onClick={() => this.updateSelectedCell()}
>
View properties
</Button>
<List>{this.renderPropertyList()}</List>
</div>
You must also return the result from renderPropertyList and return the JSX from the function given to map as well.
renderPropertyList() {
return this.state.cellProperties.map(key => {
return <PropertyBarItem name={key.nodeName} value={key.nodeValue} />
})
}
You're missing the return statement:
renderPropertyList() {
return this.state.cellProperties.map(key => {
<PropertyBarItem name={key.nodeName} value={key.nodeValue} />
})
}
Also, be sure to invoke the method:
if (this.state.selectedCell != null) {
return (
<div>
<Button variant="contained" color="primary" fullWidth={true} onClick={() => this.updateSelectedCell()}> View properties </Button>
<List>
{this.renderPropertyList()}
</List>
</div>
)
}

Resources