How to replace a word with a link - javascript

I need to replace a word and insert a link instead.
An example of how I want to do:
const text = "Edit src/App.js and save to reload."
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
{text.replace("Edit", <a
className="App-link"
href="https://reactjs.org"
target="_new"
rel="noopener noreferrer"
></a>)}
</p>
</header>
</div>
);

The JS function string.replace() expects two string parameters, but instead of the second string you supply a JSX <a> element.
Note that JSX is definitely not text, it may just look like it if you are not used to it. All JSX tags are translated into calls to React.createElement(), the result of which is a React object and not a string.
To solve it, you need to convert the string into parts, modify what needs modifying (while making sure that the React key requirement for items in a collection is fulfilled), then render the result, as in the following demo:
class Home extends React.Component {
render() {
const logo = null;
const text = "Edit src/App.js and save to reload."
// Create array:
const parts = text.split(" ");
// Modify array to contain JSX elements: one link, the rest Fragments, because every item
// in a collection needs a key to prevent React warnings.
// Also manually inserted back the spaces that went missing due to the split operation.
for (let i = 0; i < parts.length; i++) {
if (parts[i] === "Edit")
parts[i] = <a key={i} className="App-link" href="https://reactjs.org" target="_new" rel="noopener noreferrer">Edit</a>;
else
parts[i] = <React.Fragment key={i}>{" " + parts[i]}</React.Fragment>;
}
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
{parts}
</p>
</header>
</div>
);
}
}
ReactDOM.render(<Home />, document.getElementById('react'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Related

React: how to reference an external function?

I have onClick events in my html that calls a function to get the alt value of each list item (so getting the movie name). I want the next step to simply get the single value that the function got and insert it into a separate webpage. How would I go about doing it? I gave it a try but I'm still very new to react, so I'm aware this doesn't work.
My html:
<div class="now-showing">
<ul class="movie-items">
<li>
<img src="/images/movie-a.jpg" alt="Movie A">
<button>BOOK</button>
</li>
<li>
<img src="/images/movie-b.jpg" alt="Movie B">
<button>BOOK</button>
</li>
<li>
<img src="/images/movie-c.jpg" alt="Movie C">
<button>BOOK</button>
</li>
</ul>
</div>
Script:
// getting movie name for movie bookings
let filmTitle = [];
function getMovieName(e) {
let link = e.target;
let img = link.closest("li").querySelector("img");
let item = img.alt;
filmTitle.push(item);
};
// input movie title to schedule page
function AddTitle() {
return (
<div className="schedule-heading">
<h2>Step 1: Select screening for {filmTitle}</h2>
</div>
)
}
ReactDOM.render(<AddTitle />, document.querySelector('.screenings'));
So far on my second webpage, I'm only getting "Step 1: Select screening for". What changes or additions would I need to make?
there what's wrong with your code:
first: u can't make img alt that saved by function exist when page reloading. so use ReactRouter instead if u wants to move to another page without reloading.
and make everything in pure react.
otherwise the img alt need to be stored in cookie or your server side.
second: react won't rerender without calling useState hook. so for react filmTitle will always blank. or u can also store it in another library for managing react state data like redux or mobx.
note this code snippet doesnt run properly because stackoverflow blocked it.
so u need to run it in your own project.
const {
BrowserRouter, Routes, Route, Outlet,Link,useNavigate} = ReactRouterDOM
function MyMovie(props){
let navigate = useNavigate();
const [data,setData] = React.useState([
{imgsrc:"/images/movie-a.jpg",imgalt:"Movie A",href:"/bookticket"},
{imgsrc:"/images/movie-b.jpg",imgalt:"Movie B",href:"/bookticket"},
{imgsrc:"/images/movie-c.jpg",imgalt:"Movie C",href:"/bookticket"}])
const bookMovie=(v)=>{
props.setFilmTitle(v.imgalt)
navigate(v.href)
}
return <div className="now-showing">
<ul className="movie-items">
{data.map(v=>
<li key={v.imgalt}>
<img src={v.imgsrc} alt={v.imgalt}/>
<button onClick={()=>bookMovie(v)}>BOOK</button>
</li>)}
</ul>
</div>
}
// input movie title to schedule page
function AddTitle(props) {
return ( <div className = "schedule-heading" >
<h2 > Step 1: Select screening for {props.filmTitle} < /h2>
</div>
)
}
function Page(){
return <div>
Welcome!
<Outlet/>
</div>
}
function App(){
const [filmTitle,setFilmTitle] = React.useState([])
return <BrowserRouter>
<Routes>
<Route path="/" element={<Page />}>
<Route index element={ <MyMovie filmTitle={filmTitle} setFilmTitle={setFilmTitle}/>} />
<Route path="bookticket" element={ <AddTitle filmTitle={filmTitle}/>}/>
</Route>
</Routes>
</BrowserRouter>
}
ReactDOM.render( <App /> , document.querySelector('.screenings'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/history#5/umd/history.development.js" crossorigin></script>
<script src="https://unpkg.com/react-router#6/umd/react-router.development.js" crossorigin></script>
<script src="https://unpkg.com/react-router-dom#6/umd/react-router-dom.development.js" crossorigin></script>
<div class="screenings">
</div>

Javascript attribute - onClick and onClickOverThere for dropDown

I have reactJs app and I have made a custom dropDown with a div that I set an onClick attribute to open dropDown and close it.
but also I want to close it when the user clicks to another part of the site.
<div
onClick={() => setNoneQuote(noneQuote ? false : true)}
className="selected-drop-down"
>
<span className="dropDownText">{selectedQuoteCurrency}</span>
<img
className="dropDownIcon"
src={require("../assets/image/arrow/dropDown-Arrow.png")}
width="15px"
alt="arrow"
/>
</div>
I try onMouseDown instead of onClick according to this answer ==> stackoverflow ,but I don't know why it doesn't work for me :(
const dropdownElement= document.querySelector("choose an id or a specific class")
window.onclick = function(event) {
if (event.target !== dropdownElement) {
dropdownElement.style.display = "none"; // or any other function that you want to call
}
}
this may not be the exact code to fix your problem but you can use the logic
You could do it in different ways, but I will show you solution that I used in one of my projects.
So, I used <header> and <main> tags where I had all my Components. And in those tags i used eventListener with a callback function, like this:
<header onClick={handleClick}>
<Nav />
<Greeting />
<Sidebar />
</header>
and
<main onClick={handleClick}>
<Description />
<Icons />
<Prices />
<Gallery />
<NecessaryInfo />
<Location />
<GalleryModal />
<ConditionsModal />
</main>
In a callback function handleClick I checked where user could click and to do that I used next logic of pure JS:
!e.target.classList.contains("menu-open") &&
!e.target.classList.contains("menu-links") &&
!e.target.parentElement.classList.contains("menu-links") &&
!e.target.parentElement.parentElement.classList.contains("menu-links") &&
closeSidebar();
Function closeSidebar() is simple:
const closeSidebar = () => {
setIsSidebarOpen(false)};
In your code instead of using setNoneQuote(noneQuote ? false : true) you could also use: setNoneQuote(!noneQuote). Exclamation mark before value always will change it to the oposite.

Display image from .map array (React)

setForecast(res2.data.list.map(item => [
<div className="each_data_point">
<li className="date_time" key={item.dt_txt}>{`Date & Time: ${item.dt_txt}`}</li>,
<img className="icon" key={item.weather[0].icon}>{`https://openweathermap.org/img/w/${item.weather[0].icon}.png`}</img>,
<li className="main_temp" key={item.main.temp}>{`Temp: ${item.main.temp}`}</li>
</div>
]
))
......
return (
<div>
<div className="five_day_forecast">
<div className="temp_body">
// Display here with Date/Time & Main Temp.
<p>{forecast}</p>
</div>
</div>
Is it possible to render an image from array.map() within React. When I run this, the DOM clears completely to white screen.
Using src in the img tag to render image
<img className="icon" key={item.weather[0].icon} src={`https://openweathermap.org/img/w/${item.weather[0].icon}.png`} />
And put the key in div instead in the children.
Not sure why you are doing it, but setting JSX in your state seems strange.
Try something like this, assuming res2.data.list has the list of values.
<div className="five_day_forecast">
<div className="temp_body">
// Display here with Date/Time & Main Temp.
<p>
{res2.data.list && res2.data.list.length >0 && res2.data.list.map(item => [
<div className="each_data_point">
<li className="date_time" key={item.dt_txt}>{`Date & Time: ${
item.dt_txt
}`}</li>
,
<img
className="icon"
key={item.weather[0].icon}
>{`https://openweathermap.org/img/w/${
item.weather[0].icon
}.png`}</img>
,
<li className="main_temp" key={item.main.temp}>{`Temp: ${
item.main.temp
}`}</li>
</div>
])}
</p>
</div>
</div>
Putting markup in state is a weird anti-pattern. State is really there to just store data not markup. You can use a function to create the JSX from mapping over the data.
You should be adding the source of the image to the src attribute of the img element.
Keys should be added to parent elements.
const imgSrc = `https://openweathermap.org/img/w/${item.weather[0].icon}.png`;
<img src={imgSrc} />
// `fetch` your data, and add it to state
setForecast(res2.data.list);
// `map` over the data and create the markup
function getMarkup() {
const imgSrc = `https://openweathermap.org/img/w/${item.weather[0].icon}.png`;
return forecast.map(item => {
<div className="each_data_point" key={item.dt_txt}>
<li className="date_time">{`Date & Time: ${item.dt_txt}`}</li>,
<img src={imgSrc} className="icon" />,
<li className="main_temp">{`Temp: ${item.main.temp}`}</li>
</div>
});
}
return (
<div>
<div className="five_day_forecast">
<div className="temp_body">
// Call the function to return the markup
// build from state
{getMarkup()}
</div>
</div>
);

React JSX expressions must have a parent element error when adding a second <div>

When I try to add another react returns the error JSX Expressions must have one parent element. I don't see why this is as it has a parent element.
return (
<div className="loginButton">
<header className="loginButton">
<button className='discordLogin' id='login'
href="link-here"></button>
</header>
</div>
<div className="App">
<header className="App-header">
<img key={speed} src={logo} style={animationStyle} className="App-logo-circle" id='spinnerLogo'
alt="Spinning logo" />
<p>Hello, and welcome to the begining of the Swiss Plus Website. <strong>We hope you enjoy your stay</strong>
</p>
<button className='App-button' id='fastLogoButton' onClick={faster}>Increase Spin Speed!</button>
<button className='App-button' id='slowLogoButton' onClick={slower}>Decrease Spin Speed!</button>
</header>
</div>
);
PS. The error happens at the ) of the return.
You have this error because you are returning two elements simultaneously.
Both your divs need to be wrap in a parent element.
You could use React.Fragment to do this. As mentioned in the docs(https://reactjs.org/docs/react-api.html#reactfragment)
The React.Fragment component lets you return multiple elements in a render()
method without creating an additional DOM element
return(
<React.Fragment>
<div className="loginButton">
<header className="loginButton">
<button className='discordLogin' id='login'
href="link-here"></button>
</header>
</div>
<div className="App">
<header className="App-header">
<img key={speed} src={logo} style={animationStyle} className="App-logo-circle"
id='spinnerLogo'
alt="Spinning logo"
/>
<p>Hello, and welcome to the begining of the Swiss Plus Website. <strong>We hope
you enjoy your stay</strong>
</p>
<button className='App-button' id='fastLogoButton' onClick={faster}>
Increase Spin Speed!
</button>
<button className='App-button' id='slowLogoButton' onClick={slower}>
Decrease SpinSpeed!
</button>
</header>
</div>
</React.Fragment>
);
React components require you to return only one element. A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM.
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
Usually these elements are wrapped for example inside a div. In most cases the wrapper div is “irrelevant” and is only added because React components require you to return only one element. Read more on fragment and check official documentation.

Pass object as parameter in Link

I am using <Link> and trying to pass in my thumb_id (if I console log it is just a string value) to my editvideo page as a parameter. How do I accomplish this?
Code Snippet
const { thumbnail, _id } = this.props;
return thumbnail.map(thumb => {
console.log(thumb._id);
return (
<div key={thumb._id} className="row__inner">
<Link to="/editvideo/:thumb._id">
<div className="tile">
<div className="tile__media">
<img
className="tile__img"
id="thumbnail"
src={thumb.thumbnail}
alt=""
/>
</div>
</div>
</Link>
</div>
Params using temp literal
Console log of thumb_id
You can use a template literal to insert the value of the variable in the string.
<Link to={`/editvideo/${thumb._id}`}>

Categories