React: Preview content while typing - javascript

I have a simple list where I'm adding media content.
I'm using Embed to display the media contents.
When I want to enter a media link suck as Youtube/twitter .., I want to be able to preview it after pasting it and before clicking on Add.
I tried to add an onChange but didn't work. How to do so ?
https://codesandbox.io/s/vigorous-greider-seycx?file=/src/App.js:0-1201
import React, { useState } from "react";
import Embed from "react-embed";
export default () => {
const reactList = [
{
id: "2",
title: "Twitter",
media: "https://twitter.com/Betclic/status/1382074820628783116?s=20"
}
];
const [links, setLinks] = useState(reactList);
const [media, setMedia] = React.useState("");
function handleChange(event) {
setMedia(event.target.value);
}
function handleAdd() {
const newList = links.concat({ media });
setLinks(newList);
}
return (
<div>
<div>
<input type="text" value={media} onChange={handleChange} />
<div
style={{ height: "250px", width: "500px", border: "3px solid black" }}
>
Preview
<Embed url={media} onChange={handleChange} />
</div>
<button type="button" onClick={handleAdd}>
Add
</button>
</div>
<ul>
<div style={{ width: "50vh" }}>
{links.reverse().map((url, indexurl) => (
<li key={url.id}>
<div>{url.title}</div>
<Embed url={url.media} />
</li>
))}
</div>
</ul>
</div>
);
};
I think I have to set an automatic refresh for the component, because when I set the link in a modal, after closing and reopening the modal, it works. What do you think?

Related

How do I close the modal window in react when clicking on the Add product button?

everyone. I can't write the code to close the modal window in React. I don't know how this can be done, I need that when clicking on the "Add" button, a modal window opens, the user enters the data, and clicking on the "Add product" button, the window closes immediately
Code:
import React from 'react';
import CatalogProducts from "./CatalogProducts";
import Info from "./Info";
import CreateProduct from "./CreateProduct";
import {Button} from 'react-bootstrap';
import Popup from 'reactjs-popup';
import 'reactjs-popup/dist/index.css';
import '../css/popup.css'
const Main = () => {
return (
<div>
<div className="d-flex justify-content-between" style={{ width: '33rem', margin: '10px' }}>
<Popup contentStyle={{width: "unset", backgroundColor: "red", border: "none", background: "none"}}
trigger={<Button> Add </Button>} modal>
<CreateProduct/>
</Popup>
<input placeholder={'search'}/>
<span>sort by</span>
<input/>
</div>
<CatalogProducts></CatalogProducts>
<Info></Info>
</div>
);
};
export default Main;
import React from 'react';
import {useDispatch} from "react-redux";
import {addProductAction} from "../action/productsAction";
import {ConfigProduct} from "../Utils/configProduct";
import '../css/popup.css'
import '../css/flex.css'
import {Button} from "react-bootstrap";
const CreateProduct = () => {
const dispatch = useDispatch()
const newProduct = new ConfigProduct()
function addProd() {
dispatch(addProductAction(newProduct))
}
return (
<div className = "popup">
<h2 style={{textAlign: "center", color: "red"}}>New product</h2>
<input className="item" placeholder="id" onChange={e => newProduct.idProd = e.target.value}/>
<input className="item" placeholder="info" onChange={e => newProduct.name = e.target.value}/>
<input className="item" placeholder="price" onChange={e => newProduct.infoProd = e.target.value}/>
<input className="item" placeholder="date" onChange={e => newProduct.price = e.target.value}/>
<input className="item" placeholder="enter url" onChange={e => newProduct.date = e.target.value}/>
<p>
<Button onClick={addProd}>Add product</Button>
</p>
</div>
);
};
export default CreateProduct;
I tried setting a flag to change the component class. but it didn't work out for me
In your main.js
[open, setOpen] = useState(false)
const closeModal = () => setOpen(false)
return (
<div>
<div className="d-flex justify-content-between" style={{ width: '33rem', margin: '10px' }}>
<Popup
contentStyle={
{width: "unset", backgroundColor: "red", border: "none", background: "none"}
}
trigger={<Button> Add </Button>}
modal
>
<CreateProduct closeModal={closeModal}/>
</Popup>
<input placeholder={'search'}/>
<span>sort by</span>
<input/>
</div>
<CatalogProducts></CatalogProducts>
<Info></Info>
</div>
)
and inside your CreateProduct.js
const CreateProduct = ({ closeModal }) => {
// your code
function addProd() {
dispatch(addProductAction(newProduct))
closeModal()
}
// rest of your code
)

Displaying selected options in custom multiselect dropdwown as tags - React

I've custom multiselect dropdown which is implemented as given below:
const RequestExpertSupport = function Basic({
data,
onSelectedItemsChanged,
selectedItemsIndices,
}) {
const props = {
data: [
"My account and profile",
"Understanding my footprint",
"Target setting",
"Specific actions",
"Creating a plan",
"Finance, funding and grants ",
"Using the Carbon Planner platform",
"Other",
],
selectedItemsIndices: [],
};
//
const handleSelectedItemsChanged = useCallback(
selectedItemsIndices => {
onSelectedItemsChanged(selectedItemsIndices);
},
[onSelectedItemsChanged]
);
function onSelectedItemsChanged(selectedItemsIndices) {
console.log(selectedItemsIndices);
}
function renderItem(datum, index) {
return <span>{datum}</span>;
}
return (
<RequestExpertSupportDiv>
<div className="container">
<div className="formContainer">
<form>
<label className="helpLabel">What would you like help with?</label>
<DropdownListTrigger
dropdownList={
<MultiSelectDropdownList
id="multiSelectDrop"
data={props.data}
onSelectedItemsChanged={handleSelectedItemsChanged}
renderItem={renderItem}
selectedItemsIndices={selectedItemsIndices}
/>
}
position="right"
className="ddlFilter"
>
<button className="zb-button zb-button-secondary zb-button-with-icon-after">
<span>Choose topic(s)</span>
<Icon
name="chev-down-xsmall"
style={{
verticalAlign: "text-bottom",
}}
title={null}
/>
</button>
</DropdownListTrigger>
<div className="selectedTopics">Selected topics are:</div>
<label className="tellUsLabel">What would you like help with?</label>
<textarea
name="helpReview"
rows="4"
cols="43"
className="textArea"
style={{ width: "410px", height: "290px", marginTop: "2%" }}
placeholder="Type your message here ..."
></textarea>
<button className="sendBtn" name="sendBtn">
Send
</button>
</form>
</div>
</div>
</RequestExpertSupportDiv>
);
};
export default RequestExpertSupport;
This code fetches the indices of selected options in Multiselect dropdown.
function onSelectedItemsChanged(selectedItemsIndices) {
console.log(selectedItemsIndices);
}
Console is given below:
Now I want to display those selected options as tags like this:
This is the code for tags:
<Div
flex="flex"
display="inline-flex"
height="36px"
borderWidth="1px solid #009FAC"
borderRadius="3px"
backgroundColor="#def8fa"
justifyContent="space-around"
alignItems="center"
marginRight="10px"
marginBottom="10px"
style={{ minWidth: "92px", maxWidth: "175px" }}
>
<span
padding="0px"
fontSize="14px"
lineHeight="20px"
fontWeight="400"
marginLeft="5px"
marginRight="5px"
style={{ maxWidth: "142px" }}
>
// need to put selected options here
</span>
<img name="close-inverted-small" onClick={event => removeSelectedTopic(event, topicId)} />
</Div>
I'm not getting how to link function SelectedItemsChanged(selectedItemsIndices) with that tags frontend code to dosplay selected options as tags...
You need to put all the codes in the last part in a loop for rendering data. for example you should write last part as below by using selectedItemIncedies and data:
{ selectedItemIncedies.map ((selectedItemIndex) => { return (<Div
flex="flex"
display="inline-flex"
height="36px"
borderWidth="1px solid #009FAC"
borderRadius="3px"
backgroundColor="#def8fa"
justifyContent="space-around"
alignItems="center"
marginRight="10px"
marginBottom="10px"
style={{ minWidth: "92px", maxWidth: "175px" }}
<span
padding="0px"
fontSize="14px"
lineHeight="20px"
fontWeight="400"
marginLeft="5px"
marginRight="5px"
style={{ maxWidth: "142px" }}
>
{data.find((item, index)=> index===selectedItemIndex)}
</span>
<img name="close-inverted-small" onClick={event => removeSelectedTopic(event, topicId)} />
</Div>)})}
You'll want to render the tags using map based on the selectedItemsIndices array. First, pass the selectedItemsIndices array as props to a TagListComponent.
Once that's all set, render each of the selected tags in selectedItemsIndices in the TagListComponent
TagListComponent.js
const TagListComponent = function Basic({
selectedItemsIndices,
}) {
return (
<div>
{selectedItemsIndices.map((selectedItemIndex, index) => {
return (
<div>
<span>{data[selectedItemIndex]}</span>
</div>
);
})}
</div>
);
};
export default TagListComponent;
In the <span/> tag above, put whatever styling you'd like for the tag itself.

React forcing a full re-render on button click

Whenever I try to click on a button which essentially populates a modal and displays it, the whole page re-renders and everything is set back to default. I tried to use React dev tools profiler but it wasn't working. Can somebody tell me what I'm doing wrong? I haven't been able to figure out what's wrong here.
Here's my code
import React, { useState } from "react";
import Box from "#mui/material/Box";
import Modal from "#mui/material/Modal";
import "./rewards.css";
const json //some api response
const style = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
};
const Rewards2 = () => {
const [showModal, setModal] = useState(false);
const [modalContent, setModalContent] = useState({
modalHeader: "",
modalImg: "",
modalContent: { content: "", terms: [], redemptionSteps: [] },
});
//const [showModal, setModal] = useState(false);
//const [s]
// onClick={handleOpen(d.name, d.img)}
const handleClose = () => setModal(false);
const handleOpen = () => setModal(true);
return (
<div id="content">
<div className="content-top">
<ul>
{json.reward_partners.map(
(partner, index) => {
// eslint-disable-next-line
return (
<div
className="row"
key={index}
>
<div className="col-md-3 col-xs-3">
<div className="widget-thumb coupon_desc">
<img
src={
partner.img
}
className="mainpnplogo1"
alt="partnership-logo"
/>
</div>
</div>
<div className="col-md-6 col-xs-6">
<div className="coupon_desc">
<div>
{
partner.content
}
</div>
</div>
</div>
<div className="col-md-3 col-xs-3">
<div className="text-center coupon_desc">
THIS IS THE BUTTON LOGIC
<a
href=""
className="theme-button theme-button-small theme-red w-btn-nocase w-btn-white knowmore-btn"
data-toggle="modal"
data-target="#couponModel"
onClick={() => {
setModalContent(
partner.modal
);
handleOpen()
console.log(
"inside onCLick",showModal
);
}}
></a>
</div>
</div>
</div>
);
}
)}
</ul>
{/* <Modal open={showModal} onClose={handleClose}>
<Box sx={style}>
<h1>{modalContent.modalHeader}</h1>
<img
src={modalContent.modalImg}
alt={modalContent.modalHeader}
/>
<p>{modalContent.modalContent.content}</p>
</Box>
</Modal> */}
<Modal
className="modal fade"
id="couponModel"
tabIndex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
open={showModal}
onClose={handleClose}
>
<Box sx = {style}>
<div
className="modal-dialog model-lg"
role="document"
>
<div
className="modal-content"
id="modalBody"
>
<div className="modal-header">
<button
type="button"
className="close"
data-dismiss="modal"
>
×
</button>
<h4 className="modal-title">
<span className="">
<b>
{
modalContent.modalHeader
}
</b>
</span>
</h4>
</div>
</div>
</div>
</Box>
</Modal>
</div>
</div>
);
};
export default Rewards2;
P.S please do ignore the redundant divs, I cut out a lot of content to show only the relevant parts.
EDIT: Highlighted the Button Logic
The issue here is with <a /> element. You can use the button instead of <a /> as on click anchor tag execute its basic behavior.
Here's a comparison between <a/> and <button /> element. Codesandbox.
export default function App() {
const handleClick = () => {
console.log("clicked");
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<a href="" onClick={handleClick}>
Anchor
</a>
<button onClick={handleClick}>button</button>
</div>
);
}
EDIT
If you have to use the <a /> element then you can add event.preventDefault() to prevent the default behaviour of <a/> tag.
Codesandbox
export default function App() {
const handleClick = (e) => {
e.preventDefault();
console.log("clicked");
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<a href="" onClick={handleClick}>
Anchor
</a>
<button onClick={handleClick}>button</button>
</div>
);
}

React Modal not closing via OnClick

I've set an onClick method to close the React Modal but it's not changing state. I believe there may be an issue with the openModalTwo, setOpenModalTwo but I'm not sure sure.
Here is my code:
import { Avatar } from "#material-ui/core";
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { selectUser } from "../features/userSlice";
import "../style/QuestionBox.css";
import Modal from "react-modal";
import PeopleAltOutlinedIcon from "#material-ui/icons/PeopleAltOutlined";
import { ExpandMore } from "#material-ui/icons";
import { Input } from "#material-ui/core";
import LinkIcon from "#material-ui/icons/Link";
import db from "../firebase";
import firebase from "firebase";
function QuestionBox() {
const user = useSelector(selectUser);
const [openModalTwo, setOpenModalTwo] = useState(false);
const [input, setInput] = useState("");
const [inputUrl, setInputUrl] = useState("");
const handleQuestion = (e) => {
e.preventDefault();
db.collection("questions").add({
question: input,
imageUrl: inputUrl,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
user: user,
});
setInput("");
setInputUrl("");
setOpenModalTwo(false);
};
return (
<div className="questionBox" onClick={() => setOpenModalTwo(true)}>
<div className="questionBox__info">
<Avatar src={user.photo} />
<h5>{user.displayName}</h5>
</div>
<div className="questionBox__question">
<p>Where do I start?</p>
</div>
<Modal
isOpen={openModalTwo}
onRequestClose={() => setOpenModalTwo(false)}
shouldCloseOnOverlayClick={false}
style={{
overlay: {
width: 700,
height: 600,
backgroundColor: "transparent",
boxShadow:
"box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);",
zIndex: "1000",
top: "50%",
left: "50%",
marginTop: "-300px",
marginLeft: "-350px",
},
}}
>
<div className="modal__title">
<h5>Add Question Here</h5>
<h5>Share Your Question</h5>
</div>
<div className="modal__info">
<Avatar Avatar className="avatar" src={user.photo} />
<p>
{user.displayName ? user.displayName : user.email} wants to know
</p>
<div className="modal__scope">
<PeopleAltOutlinedIcon />
<p>Public</p>
<ExpandMore />
</div>
</div>
<div className="modal__field">
<Input
required
value={input}
onChange={(e) => setInput(e.target.value)}
type="text"
placeholder="Ask where to start on your project with a specific 'How' or 'What' question."
/>
<div className="modal__fieldLink">
<LinkIcon />
<input
value={inputUrl}
onChange={(e) => setInputUrl(e.target.value)}
type="text"
placeholder="Add a link to help others understand what you want to build."
/>
</div>
<div className="modal__buttons">
<button
onClick={() => setOpenModalTwo({ openModalTwo: false })}
className="cancel"
>
Close
</button>
<button onClick={handleQuestion} type="submit" className="add">
Add Question
</button>
</div>
</div>
</Modal>
</div>
);
}
export default QuestionBox;
Don't know how react-modal exactly works but as you are setting setOpenModalTwo(true) on click on parent container of Modal, when you're trying to close the Modal (by a click I guess), you are also firing the onClick event of your parent div, and so re-open the Modal.
So either move your Modal outside of your div, or use event.preventDefault() on Modal requesting close

scrollIntoView onClick reactjs

hello I have a few buttons and I want to scroll to them when clicked.
const [active, setActive] = useState(0);
useEffect(() => {
// I´m not using useRef. is there other way to automatically scroll to the element and stop at 0 0 of the page?
})
<div style={{height: '10000px'}} />
<button onClick={() setActive(1)}>button 1</button>
<button onClick={() setActive(2)}>button 2</button>
<button onClick={() setActive(3)}>button 3</button>
<div style={{height: '10000px'}} />
as you can see there´s a lot of scroll caused by those 2 divs. the idea is to scroll down and when you reach the buttons and click the one you need. the page scrolls to that button leaving it in the top of the page
image 1: scroll in random position
image 2: when you click on button 1
image 3: when you click on button 2
image 4: when you click on button 3
For scrolling react view to top there is a simple function.
use window.scrollTo(0, 0);
inside your code try this.
<button onClick={()=> window.scrollTo(0, 0) }>button 1</button>
edited:
I could come up with this solution after you edited your question.
import React, { useRef } from "react";
export default function App() {
const button1Ref = useRef();
const button2Ref = useRef();
const button3Ref = useRef();
const handleScroll = ref => {
window.scrollTo({
behavior: "smooth",
top: ref.current.offsetTop
});
};
return (
<div className="App">
<div style={{ height: "10000px" }} />
<div>
<button ref={button1Ref} onClick={() => handleScroll(button1Ref)}>
button 1
</button>
</div>
<div>
<button ref={button2Ref} onClick={() => handleScroll(button2Ref)}>
button 2
</button>
</div>
<div>
<button ref={button3Ref} onClick={() => handleScroll(button3Ref)}>
button 3
</button>
</div>
<div style={{ height: "10000px" }} />
</div>
);
}
Please try it out. Let me know if this is what you asked for.
Edited after question asked in comment for using single component with Ref and using that component in multiple numbers:
If you want to use a single component for button then try this,
import React, { useRef } from "react";
export default function App() {
return (
<div className="App">
<div style={{ height: "10000px" }} />
<MyButton>button 1</MyButton>
<MyButton>button 2</MyButton>
<MyButton>button 3</MyButton>
<div style={{ height: "10000px" }} />
</div>
);
}
const MyButton = props => {
const buttonRef = useRef();
const handleScroll = () => {
window.scrollTo({
behavior: "smooth",
top: buttonRef.current.offsetTop
});
};
return (
<div>
<button ref={buttonRef} onClick={handleScroll}>
{props.children}
</button>
</div>
);
};
Here you want to use an event handler.
const handleClick = (e) => {
// scrollIntoView logic and set state
}
<div onClick={handleClick}/>
//action
const goDown= (e) => {
const anchor = document.querySelector('#some-id')
anchor.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
// click to scroll
<Link onClick={goDown}>Choose Health</Link>
//element you want to scroll to
<div id='some-id'>
</div>

Categories