I'm trying to create a function that selects an HTML element and changes the value in it to the value in another element using the ref, state, and effect hooks but I can't get the right effect I want
const Service = () => {
const [selected, setSelected] =
useState(false);
let change = useRef(null);
const[title, setTitle] = useState("");
useEffect(() => {
setTitle(change.current.children(0))
})
const Changer = (e)=>{
e.preventDefault()
const style = e.target;
if(selected === false){
console.log(`you clicked ${style}`);
}
setSelected( current => !current);
// let style={background: selected ?
'#6EEFB1' : ''};
// if (selected === true){
// setSelected(false)
// // let style= {styleObject.li}
// }else{
// setSelected(true)
// }
}
return(
<section className={selected ?
"serviceClicked" : "services"}>
<h1>Our Services</h1>
<div className='service-content'>
<div className='service-text' ref=.
{change}>
<h2></h2>
<p>
Syse infrans att dedade. Redar
fäsat. Älogi hypol. Antere
nydavarat och hemil.
Dist kyning. Kroska
bröllopskoordinator. Teletotal.
Mor tin.
</p>
<p>
Spejörar befaladat. Lavis
kvasideledes.
Dande dak. Anteck ur dick.
Skurkstat larad henifiera. Belogi
koliga selig.
</p>
</div>
<div className='service-list'>
<ul id='top-list'>
<li onClick={Changer}>
<img src={oby} />
{/* <div></div> */}
<p>ob/gyn</p>
</li>
<li onClick={Changer}>
<img src={neuro} />
{/* <div></div> */}
<p>neurology</p>
</li>
<li onClick={Changer}>
<img src={peds} />
{/* <div></div> */}
<p>pediatrics</p>
</li>
</ul>
<ul id='bottom-list'>
<li onClick={Changer}>
<img src={dental}/>
{/* <div></div> */}
<p>dental care</p>
</li>
<li onClick={Changer}>
<img src={cardio} />
{/* <div></div> */}
<p>cardiology</p>
</li>
<li onClick={Changer}>
<img src={ent} alt='E.N.T' />
{/* <div></div> */}
<p>ent</p>
</li>
</ul>
</div>
</div>
</section>
)
};
The h2 tag is meant to take on the value of the p tags under the li element when clicked, I've figured out how to make the content in the service text shown when the li element is clicked.
what's troubling is how to change the value of the h2 tag to whatever value the p tag of which li element is clicked.
CodeSandBox Example
Instead of using useEffect, useRef, you could simply use your useState to do all that.
I created a constant to make my/your life easier and just map though the elements (you don't need this, but I would recommend it)
const IMAGES = [
{ src: "oby", name: "ob/gyn" },
{ src: "neuro", name: "neurology" },
{ src: "peds", name: "pediatrics" },
{ src: "dental", name: "dental care" },
{ src: "cardio", name: "cardiology" },
{ src: "ent", name: "ent" }
];
<section className={title ? "serviceClicked" : "services"}>
<h2>{title}</h2>
...
<ul id="top-list">
{IMAGES.map(({ src, name }) => {
return (
<li
key={name}
onClick={() => {
setTitle(name);
}}
>
<img src={src} />
<h3>{name}</h3>
</li>
);
})}
</ul>
...
</section>
You would really want to use useRef if there's need to interact directly with the element, otherwise when dealing with only data useState/useEffect is more than enough.
Related
I am trying to run my acquisitions inside a JavaScript map, all the information is coming in, but when I put the image path on the src inside the tag img, it can't be find.
Here is the code:
productSearch(prodBusca) {
const prodPerPage = 15;
const pagesVisited = this.state.pageNumber * prodPerPage;
const displayProds = prodBusca.slice(pagesVisited, pagesVisited + prodPerPage).map(prod => {
let codigo = prod.codigo.toString();
let path = `${this.imgSrc}/${codigo.substr(0, 1)}/${codigo}.jpg`;
let img = path;
return (
<li key={codigo} className="list-group-item">
<div>
<img src={img} alt={prod.descricao} width="150" height="150" />
</div>
<div>
<ul>
<li>
{prod.descricao}
</li>
<li>
{prod.preco}
</li>
</ul>
</div>
</li>
);
})
const pageCount = Math.ceil(prodBusca.length / prodPerPage);
const changePage = ({ selected }) => {
this.setState({ pageNumber: selected });
};
return (
<div>
<section className="secaoProd">
<ul className="list-group list-group-horizontal">
{displayProds}
</ul>
</section>
<div>
<ReactPaginate previousLabel={'<<'} nextLabel={'>>'} pageCount={pageCount} onPageChange={changePage}
containerClassName="paginationBttns"
previousLinkClassName="previousBttn"
nextLinkClassName="nextBttn"
disabledClassName="paginationDisabled"
activeClassName="paginationActive"
/>
</div>
</div>
)
}
enter image description here
The application is in ASP.Net and React
Here's what I've have so far - Full working view https://codesandbox.io/s/hungry-elbakyan-v3h96
Accordion component:
const Accordion = ({ data }) => {
return (
<div className={"wrapper"}>
<ul className={"accordionList"}>
{data.map((item) => {
return (
<li className={"accordionListItem"} key={item.title}>
<AccordionItem {...item} />
</li>
);
})}
</ul>
</div>
);
};
const AccordionItem = ({ content, title }) => {
const [state, setState] = useState({
isOpened: false
});
return (
<div
className={cn("accordionItem", state.isOpened && "opened")}
onClick={() => setState({ isOpened: !state.isOpened })}
>
<div className={"lineItem"}>
<h3 className={"title"}>{title}</h3>
<span className={"icon"} />
</div>
<div className={"inner"}>
<div className={"content"}>
<p className={"paragraph"}>{content}</p>
</div>
</div>
</div>
);
};
When I click on the accordion item nothing happens. I can see the content appears in inspect and the state changes as expected but it doesn't slide down. Did I miss something in my css or component?
Here is what I was able to achieve. You may not like it completely(animations). But things seems sorted
https://codesandbox.io/s/relaxed-babbage-2zt4f?file=/src/styles.css
props name was not right for accordion body
and styles need to be changes once the accordion is in open state.
You need to add or remove the className inner when state.isOpen so you can see your content
I'm using react and have a list with images, when hovered them it shows a text and when clicked it opens a modal, but each "li" has different content that goes in the modal. The problems is that every item of the list open only one modal, the last one, how can I do to open the correct modal?
Modal code
constructor(props) {
super(props);
this.state = {
visible : false
}
}
openModal() {
this.setState({
visible : true,
});
}
closeModal() {
this.setState({
visible : false,
});
}
list with the modal
<li className="bor">
<img src={bor}/>
<span className="first">teste</span>
<span className="second">veja o case completo</span>
<input type="button" onClick={() => this.openModal()} />
<section>
<Modal className="modal" visible={this.state.visible} width="90%" height="90%" effect="fadeInUp" onClickAway={() => this.closeModal()}>
<div className="close">
<a href="javascript:void(0);" onClick={() => this.closeModal()}>X</a>
</div>
<div>
<h1>teste1</h1>
</div>
</Modal>
</section>
</li>
<li className="baz">
<img src={baz}/>
<span className="first">teste2</span>
<span className="second">veja o case completo</span>
<input type="button" onClick={() => this.openModal()} />
<section>
<Modal className="modal" visible={this.state.visible} width="90%" height="90%" effect="fadeInUp" onClickAway={() => this.closeModal()}>
<div className="close">
<a href="javascript:void(0);" onClick={() => this.closeModal()}>X</a>
</div>
<div>
<h1>teste2</h1>
</div>
</Modal>
</section>
</li>
As #FatemehQasemkhani said it is best practice to use single modal & pass corresponding data like below. I approaced same way & it is working fine. I am taking some dummy data inside items. Whenever user is clicking on any list(li) item I am storing that currrent clicked item inside activeItemData and passing that value in modal.
import React, { Component } from "react";
import Modal from "react-awesome-modal";
class ProList extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
activeItemData: "",
items: [
{
desc: "this is item 1 "
},
{
desc: "this is item 2"
}
]
};
}
closeModal() {
this.setState({
visible: false
});
}
handleCurrentItem = item => {
// you can set two properties in setState or you can set visible property in callback also...
this.setState(
{
activeItemData: item.desc,
visible:true
},
// () => this.setState({ visible: true })
)
};
render() {
return (
<div>
<ul>
{ this.state.items.map(item => (
<li key={item.desc} onClick={() => this.handleCurrentItem(item)}>
{item.desc}
</li>
))}
</ul>
<Modal
className="modal"
visible={this.state.visible}
width="90%"
height="90%"
effect="fadeInUp"
onClickAway={() => this.closeModal()}
>
<div className="close">
<a href="javascript:void(0);" onClick={() => this.closeModal()}>
X
</a>
</div>
<div>
<h1>{this.state.activeItemData}</h1>
</div>
</Modal>
</div>
)
}
}
I want to convert functional component in React to class based component, because I want to make use of state property.
Currently I have this component which has 2 props.
const VideoListItem = ({video, onVideoSelect}) => {
const imageUrl=video.snippet.thumbnails.default.url;
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title}</div>
</div>
</div>
</li>
)
}
I tried to convert it to class and ended up with this:
class VideoListItem extends React.Component {
render() {
const {video} = this.props.video
const imageUrl=video.snippet.thumbnails.default.url;
const{onVideoSelect} =this.props.onVideoSelect
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title}</div>
</div>
</div>
</li>
)
}
}
However It does not work, I get errors. I guess it has something to do with 2 props being in the component. Anyone has idea how can I change the first code to be a class component?
Your destructuring is a bit off:
const { video } = this.props.video;
const{ onVideoSelect } = this.props.onVideoSelect;
should be something like:
const { video } = this.props;
const{ onVideoSelect } = this.props;
and you can combine these if you want:
const { video, onVideoSelect } = this.props;
I want each this.state.title to align according to a different classname.
I tried using css flex boxes/nth-of-type/nth-child, but it did not play nicely with React.
I'm using this.state to get my objects.
My unsuccessful attempt
render: function () {
let className
var newVar = !someVar;
switch(someVar) {
case odd:
className= "post-1 line";
break;
case even:
className = "post-2 right-align line";
break;
}
return (
<article class={I WANT THIS TO FILL FROM SWITCH}>
<div class="s-12 l-6 post-image">
<a href="post-1.html">
<img src="/post1.jpg">
</a>
</div>
<div class="s-12 l-5 post-text">
<a href="#">
<h2>{this.state.title}</h2>
</a>
<p>Testing
</p>
</div>
<div class="s-12 l-1 post-date">
<p class="date">28</p>
<p class="month">feb</p>
</div>
</article>
);
}
});
react rewrite class attribute as className,see react for more details.
render: function () {
let className = ['post-2 right-align line', 'post-1 line'][someVar % 2];
return (
<article className={className}>
<div className="s-12 l-6 post-image">
<a href="post-1.html">
<img src="/post1.jpg"/>
</a>
</div>
<div className="s-12 l-5 post-text">
<a href="#">
<h2>{this.state.title}</h2>
</a>
<p>Testing
</p>
</div>
<div className="s-12 l-1 post-date">
<p className="date">28</p>
<p className="month">feb</p>
</div>
</article>
);
}
The 'someVar' is local variable ? You can try write it in state, Via this.setState mutate it for your need.
here is the whole example like this:
class Item extends Component {
render() {
let {index, title}=this.props;
let className = ['post-2 right-align line', 'post-1 line'][index % 2];
return <li key={index} id={index} className={className}>{title}</li>
}
}
class TodoList extends Component {
render() {
let i = 0;
let itemFactory = (props = {}) => {
return <Item key={i} index={i++} {...props}/>
};
return (<ul>
{this.props.items.map((item) => itemFactory({title: item}))}
</ul>);
}
}
ReactDOM.render(
<TodoList items={['first', 'second', 'last']}/>,
document.getElementById('container')
);