My project is a bit trouble when I tried to add Component on a function.
When I click on the text:
<td
className='text-primary'
style={{
maxHeight: '21px',
width: '8%',
maxWidth: '300px'
}}
onClick={(event) => {onEditLangClicked(event,item)}}
>
{item.language_name}
</td>
it will go to onEditLangClicked:
function onEditLangClicked(event,lang){
setEditMode(true);
setLang(lang);
<ModalAddNgonNgu />
console.log/(lang);
}
And I should go to Component:
const ModalAddNgonNgu = (props) => {
//Kind of stuff
return (
<>
<button type="button" className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#myModalAddNgonNgu" style={{ fontSize: '14px' }}>
Thêm
</button>
//Just some HTML
}
export default ModalAddNgonNgu;
So what should I change in onEditLangChecked(event,lang)? Thank you
Create state to indicate when you did mount your component like
const [visible, setVisible] = useState(false);
Changing the state you change the component to display. For example
visible ? <Component1 />: <Component2 />
Related
So I have this custom collapse where I switch between 2 styles of displaying based on this const [disabled, setDisabled] = useState(true); state. Then I use this custom collapse on another component where after I click on a button I will want to change to another style of display which is the 3rd style of display. How exactly do I get the state then change it on the original component?
Here's the custom collapse in ./CustomCollapse.js
const CustomCollapse = (props) => {
const [disabled, setDisabled] = useState(true);
return (
<StyledCollapse onChange={() => setDisabled(prev => !prev)}>
<AntCollapse.Panel
header={props.header}
key="1"
showArrow={false}
bordered={false}
extra={
<span>
<span style={{ color: "#0076de", float: "right" }}>
// Here's where I wanna add the 3rd style
{disabled ? <div id={styles.themeBox}><p>+10</p></div> : <img src={arrowDownIcon} alt="" style={{height:'1.2em', marginLRight:'10px', width:'auto', objectFit:'contain'}} />}
</span>
</span>
}
>
{props.children}
</AntCollapse.Panel>
</StyledCollapse>
);
};
Here's where I want to change the state in ./FollowTelegram.js:
import AntCollapse from './CustomCollapse';
let [followed, setFollowed] = useState(false);
const setFollowed = () => {
setFollowed(prev => !prev)
}
// {...other code}
<AntCollapse id={styles.telegramHeader1} header="Follow XXX on Telegram Announcement Channel">
<Row type='flex' align='middle' justify='center'>
<Button href={links[0]} target="_blank" style={buttonStyle1} onClick={() => setClicked(false)}>
<Icon type="link" style={{ color: '#fff' }} theme="outlined" />
Subscribe
</Button>
</Row>
<span className={styles.greyLine}> </span>
<Row type='flex' align='middle' justify='center'>
//Here's where I wanna change followed to true
<Button onClick={setFollowed} style={buttonStyle2} disabled={clicked}>Continue</Button>
<Button type='text' style={{color:'#EB7B59', border:'#f7f7f7', background:'#f7f7f7',height: "2em", fontSize:'16px', margin:'10px 0 0 10px'}}>Cancel</Button>
</Row>
</AntCollapse>
But how can I pass the state to ./CustomCollapse to know and change the style?
You can pass the disabled value to the child component (CustomCollapse ) by adding a property.
import React, { useState, useEffect } from 'react'
const CustomCollapse = (props) => {
const [disabled, setDisabled] = useState(true);
useEffect(() => {
setDisabled(props.isDisabled)
}, [props.isDisabled])
return (
<StyledCollapse onChange={() => setDisabled(prev => !prev)}>
<AntCollapse.Panel
header={props.header}
key="1"
showArrow={false}
bordered={false}
extra={
<span>
<span style={{ color: "#0076de", float: "right" }}>
// Here's where I wanna add the 3rd style
{disabled ? <div id={styles.themeBox}><p>+10</p></div> : <img src={arrowDownIcon} alt="" style={{ height: '1.2em', marginLRight: '10px', width: 'auto', objectFit: 'contain', float: 'left' }} />}
</span>
</span>
}
>
{props.children}
</AntCollapse.Panel>
</StyledCollapse>
);
};
and in the parent component
import AntCollapse from './CustomCollapse';
//inside your parent component
let [followed, setFollowed] = useState(false);
const [disabledCollapse, setDisabledCollapse] = useState(true)
// {...other code}
const toggleDisabledCollapse = () => {
setDisabledCollapse(prev => !prev)
}
return <AntCollapse isDisabled={disabledCollapse} id={styles.telegramHeader1} header="Follow XXX on Telegram Announcement Channel">
<Row type='flex' align='middle' justify='center'>
<Button href={links[0]} target="_blank" style={buttonStyle1} onClick={() => setClicked(false)}>
<Icon type="link" style={{ color: '#fff' }} theme="outlined" />
Subscribe
</Button>
</Row>
<span className={styles.greyLine}> </span>
<Row type='flex' align='middle' justify='center'>
//Here's where I wanna change followed to true
<Button onClick={toggleDisabledCollapse} href={links[0]} target="_blank" style={buttonStyle2} disabled={clicked}>Continue</Button>
<Button type='text' style={{ color: '#EB7B59', border: '#f7f7f7', background: '#f7f7f7', height: "2em", fontSize: '16px', margin: '10px 0 0 10px' }}>Cancel</Button>
</Row>
</AntCollapse>
I'm using Material-UI at my React Project and Im trying create a component that render a drawer and some other components inside it. But I'm having a lot of issues with the open drawer function... I tried passing simply as a state props but then my drawer won't close...
interface Props {
cartOpen: boolean;
}
const CartDrawer: React.FunctionComponent<Props> = ({ cartOpen }) => {
const classes = useStyles();
return (
<Drawer anchor="right" open={cartOpen}>
<div className={classes.cartDrawerDiv}>
<div className={classes.cartTitle}>
<List>
<ListItem>
<ShoppingCartIcon className={classes.icon} />
<Typography
style={{
fontFamily: "Montserrat, sans-serif",
fontSize: "15px",
fontWeight: 800,
marginLeft: "8px",
}}
>
1 Item
</Typography>
</ListItem>
</List>
</div>
<Divider />
</div>
</Drawer>
);
};
export default CartDrawer;
Example of a component using it...
...
<Button
color="secondary"
size="large"
variant="contained"
className={classes.buyButton}
style={{ fontWeight: 600 }}
onClick={() => setCartOpen(true)}
>
COMPRAR
</Button>
</div>
</div>
</div>
<CartDrawer cartOpen={cartOpen} />
You should add onClose to close Drawer
<CartDrawer cartOpen={cartOpen} onClose={() => setCartOpen(false)} />
interface Props {
cartOpen: boolean;
onClose: () => void
}
const CartDrawer: React.FunctionComponent<Props> = ({ cartOpen, onClose }) => {
const classes = useStyles();
return (
<Drawer anchor="right" open={cartOpen} onClose={onClose}>
...
I'm mapping through data, I want to click on an image and have a modal popup with the data.title and data.info. Each modal is only showing the last data from my array. I've read that all the modals are popping up together and I'm only seeing the last one but I don't quite understand how to solve the problem, particularly with function components in React. TIA
export default function SomeComponent
const [modalIsOpen, setModalIsOpen] =
useState(false);
const customStyles = {
content: {
top: '35%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
width: '60%',
transform: 'translate(-40%, -10%)',
},
}
return (
<div className="container">
{ somedata.map((data) =>
(<div className='item' key={data.id} >
<img src={data.img} alt='' onClick={()=> setModalIsOpen(true)} />
<Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} style={customStyles}>
<h1>{data.title</h1>
<p>{data.content</p>
<div>
<button onClick={() => setModalIsOpen(false)}>X</button>
</div>
</Modal>
</div>))}
</div>
</div>
);}
You should use only one instance of Modal component and pass on the data of the clicked image to it using a state. Each time you click on an image, the data for modal should be updated with the data of the clicked image. See the example below. I've modified your code to make it work.
export default function SomeComponent() {
const [modalIsOpen, setModalIsOpen] = useState(false);
const [modalData, setModalData] = useState(null);
const customStyles = {
content: {
top: '35%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
width: '60%',
transform: 'translate(-40%, -10%)',
},
}
return (
<>
<div className="container">
{somedata.map(data => (
<div className='item' key={data.id} >
<img
src={data.img}
alt=''
onClick={()=> {
setModalData(data);
setModalIsOpen(true);
}
/>
</div>
))}
</div>
<Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} style={customStyles}>
<h1>{modalData.title}</h1>
<p>{modalData.content}</p>
<div>
<button onClick={() => setModalIsOpen(false)}>X</button>
</div>
</Modal>
</>
)
}
i expect the hook to be updated(and i want every time to keep only one object i dont want to save previous value)
my hooks:
const [rooms, setrooms] = useState([]);
const [roomFilter,setRoomFilter]=useState([])
function to update roomFilter hook:
const deleteR=(i)=>{
var temp=rooms.filter((element,index)=>(index==i))
setRoomFilter([temp[0].Name])
somehow it shows nothing in roomFilter hook after update
i have tried also initiakize my hook like this:
const [roomFilter,setRoomFilter]=useState({})
i dont understand why
edit
i am using function deleteR like this:
<Route exact path="/"component={() => { return <HomeScreen rooms={rooms} filter={deleteR} room={roomFilter} /> }}
from HomeScreen component i have two more components :
HomeScreenRooms and Room
function roomFilter is been sent from app to HomeSCreen >to HomeScreenRooms
HomeScreen:
<HomeScreenRooms rooms={props.rooms} filter={props.filter} room={props.roomFilter} />
HomeScreenRooms:
{props.rooms.map((element) => {
return ( <div style={{ width: "100px",height: "100px",position: "relative",
left: "-150px",top: "-100px",display: "inline" }}>
<Link to="/room"><button onClick={() => {props.filter(element.index) }} style={{ width: "116px",height: "116px",backgroundColor: element.color,position: "relative",fontWeight: "bold", color: "white",fontSize: "18px", border: "3px solid rgb(84,84,84)" }}>
<p>
<span>{element.room} </span>
</p>
<p>
<span
style={{ fontWeight: "bold", color: "rgb(84,84,84)" }}>{element.Name}
</span>
</p>
</button>
</Link>
try this
const deleteR = (i) => {
setRoomFilter((prevState) => {
var temp = prevState.filter((element, index) => index == i); //consider using a unique id
return [temp[0].Name];
});
};
note: I would recommend you use some sort of unique identification to remove from a list, and not an index.
I decided to use react-simple-popover for my popover needs. Documentation is here: https://github.com/dbtek/react-popover. The problem is that the documentation is for stateful components (class components). The container prop takes in this of the current class component, but I am using stateless component with hooks. What do I pass in place of the "this" keyword in this way?
import React, { useRef, useState } from "react";
import styled from "styled-components";
import Popover from "react-simple-popover";
import { HelpQuestion } from "../UI/Common";
const Wrapper = styled.div`
margin-bottom: 1rem;
`;
export const TextInput = styled.input`
border: 1px solid
${(props) => (props.dark ? "#37394B" : props.theme.lightGray)};
padding: 0.5rem 1rem;
width: 100%;
border-radius: 10px;
color: ${(props) => (props.dark ? "white" : "black")};
background-color: ${(props) => (props.dark ? "#37394B" : "white")};
`;
export default function TextField({
label,
value,
onChange,
onClick,
error,
type,
placeholder,
help,
dark,
disabled,
}) {
const [isPopoverOpen, setPopoverOpen] = useState(false);
const popoverRef = useRef(null);
const componentRef = useRef(null);
return (
<Wrapper ref={componentRef}>
<div style={{ display: "flex", alignItems: "center" }}>
<TextInput
value={value}
onChange={!disabled ? onChange : () => {}}
onClick={onClick}
placeholder={placeholder}
type={type}
dark={dark}
disabled={disabled}
/>
{help && (
<div
style={{ marginLeft: "0.5rem" }}
onClick={() => setPopoverOpen(!isPopoverOpen)}
ref={popoverRef}
>
<HelpQuestion className="fas fa-question" />
</div>
)}
</div>
{error && <Error>{error}</Error>}
<Popover
placement="left"
container={componentRef.current} //doesnt work
target={popoverRef}
show={isPopoverOpen}
onHide={() => setPopoverOpen(false)}
>
<p>{help}</p>
</Popover>
</Wrapper>
);
}
How do I provide a container for popover component?
What do I pass in place of the "this" keyword in this way?
No, I don't think you can. View the source.
const Popover = props => {
if (
ReactDOM.findDOMNode(props.container) &&
ReactDOM.findDOMNode(props.container).parentElement.parentElement !==
document.body
) {
ReactDOM.findDOMNode(props.container).style.position = 'relative';
}
return (
<Overlay
show={props.show}
onHide={props.onHide}
placement={props.placement}
container={props.container}
target={p => ReactDOM.findDOMNode(props.target)}
rootClose={props.hideWithOutsideClick}
>
<PopoverContent
showArrow={props.showArrow}
arrowStyle={props.arrowStyle}
innerStyle={props.style}
style={props.containerStyle}
>
{props.children}
</PopoverContent>
</Overlay>
);
};
It doesn't appear to be well maintained and it's using ReactDOM.findDOMNode which is practically deprecated. I tried this and also tried a small class-based component wrapper. Nothing worked. Each time the reported error referred to the current ref value (componentRef.current) not being a react component.
For what its worth I suggest using a more functional component friendly Popover component. Here's an example using Material-UI's Popover component.
function TextField({
label,
value,
onChange,
onClick,
error,
type,
placeholder,
help,
dark,
disabled
}) {
const [isPopoverOpen, setPopoverOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const clickHandler = (e) => {
setPopoverOpen((open) => !open);
setAnchorEl(e.target);
};
return (
<Wrapper>
<div style={{ display: "flex", alignItems: "center" }}>
<TextInput
value={value}
onChange={!disabled ? onChange : () => {}}
onClick={onClick}
placeholder={placeholder}
type={type}
dark={dark}
disabled={disabled}
/>
{help && (
<div style={{ marginLeft: "0.5rem" }} onClick={clickHandler}>
<HelpOutlineIcon />
</div>
)}
</div>
{error && <Error>{error}</Error>}
<Popover
anchorEl={anchorEl}
open={isPopoverOpen}
onClose={() => setPopoverOpen(false)}
anchorOrigin={{
vertical: "center",
horizontal: "left"
}}
transformOrigin={{
vertical: "center",
horizontal: "right"
}}
>
<p>{help}</p>
</Popover>
</Wrapper>
);
}