Hello i'm trying to highlight the Items, with the same Id. Im using document.getElementById but i don't really know ho to do it. does anyone can help me?
I'm iterating over an Array of Objects from my Database....
return(
<div className='list'>
<Row>
{this.state.cards.map((card) => {
return(<Card
onHover={()=>{
const highlighted = document.getElementById(card.id)
highlighted.style={{backgroundColor: "blue"}}
}}
cardHeading={card.cardHeading} cardDesc={card.cardDesc}
cardPreis={card.cardPreis} cardId={card.id} bewertung={card.cardBewertung}
image={card.cardImage}/>)
})
}
</Row>
</div>
)
.... My GoogleMaps Component:
<Marker onClick={props.show}
position={{ lat: marker.latitude + 0.00201, lng:
marker.longitude + 0.00201}}
id={marker.id}
/>
id={marker.id} and cardId={card.id} are the same and i want to highlight one of them when hovering over them ... thanks in advance.
React gives you the ability for a component to control itself dynamically. So make that Card into a separate component with all of the logic you need using this.setState to control the current style of your Card. I can't test this, but this is the general idea:
return(
<div className='list'>
<Row>
{this.state.cards.map((card) => <CustomCard card={card}/>)}
</Row>
</div>
)
class CustomCard extends Component {
constructor() {
super()
this.state = {
defaultColor: true
}
}
handleClickColorChange() {
this.setState({defaultColor: !this.state.defaultColor})
}
render() {
const {card} = this.props
const customStyle = {
backgroundColor: 'blue'
}
return (
<Card
onHover={() => this.handleClickColorChange()}
style={this.state.defaultColor ? null : customStyle}
cardHeading={card.cardHeading} cardDesc={card.cardDesc}
cardPreis={card.cardPreis} cardId={card.id} bewertung={card.cardBewertung}
image={card.cardImage}
/>
)
}
}
Related
I am writing a React component like this. My goal is to render a checklist for shopping, with toggles (lower order component) that would update the state of this higher order component when clicked.
It may look something like this
1.Fruits
Banana (Button)
Kiwi Fruit (Button)
2.Other snacks
Potato chips (Button)
Instant noodles (Button)
Sugarfree mint (Button)
let shopping_list = [
{
Fruits: [
{ Banana: "banana" },
{ "Kiwi fruit": "kiwi" },
]
},
{
'Other snacks': [
{ "Potato chips": "potato_chips" },
{ "Instant noodles ": "instant_noodles" },
{ "Sugarfree mint": "sugar_free_mint" }]
}
]
class ShoppingList extends Component {
constructor(props) {
super(props);
this.btnClicked.bind(this);
this.state = {
banana: false,
kiwi: false,
potato_chips: false,
instant_noodles: false,
sugar_free_mint: false,
}
}
btnClicked = (e) => {
let obj = {};
obj[e.currentTarget.id] = !(this.state[e.currentTarget.id]);
this.setState(obj);
}
createToggle = (content, attribute) => {
return (
<Row key={attribute}>
<Col>
{content}
</Col>
<Col xs="2">
<Chips label="✓"
id={attribute} onClick={this.btnClicked} />
</Col>
</Row>
)
}
createNestedToggle = (shopping_list) => {
//console.log("creating nested toggle")
//console.log(this)
shopping_list.map( (section, index) =>
( <React.Fragment key={index}>
<Row className="table_text" style={{paddingTop: 5}}>
<Col xs="12" style={{fontWeight: "bold"}}>
{index+1}.{(Object.keys(section))[0]}
</Col>
</Row>
{ (Object.values(section))[0].map((item) => {
this.createToggle(
(Object.keys(item))[0],
(Object.values(item))[0]
)
}
)
}
</React.Fragment>
))
}
render() {
return (
<div className="animated fadeIn">
<Title type="title" content="Shopping list" />
...
{/**Some rows and columns in here */}
<div>
{this.createNestedToggle(shopping_list)}
</div>
<div>
{/**Some rows and columns in here */}
</div>
</div>)
}
}
But the shopping list wasn't rendered properly, it was missing. When I was debugging, I tried adding console log messages to the function createNestedToggle as you can see, and they're actually logged. I am not sure what exactly is wrong with the second block.
Things I've tried
I have tried writing the createToggle part into a functional component to simplify the code - however,
as I need the toggles to call back the HOC I have to make createToggle a part of ShoppingList class.
I am quite new to React JS(JS to be exact), so maybe I am doing the whole thing in a way that's
completely wrong. If you could suggest me a better way to do it, I would be very grateful as well.
Any help or hint would be appreciated, thank you :)
After I have modified the createNestedToggle function as the following and it worked
createNestedToggle = (part_iii) => {
return(
<div>
{part_iii.map( (section, index) =>
<div key={index}>
...
{
(Object.values(section))[0].map((item) => {
return(
this.createToggle(
(Object.keys(item))[0],(Object.values(item))[0] )
)
}
)
}
</div>
)}
</div>
)
}
I was always confused by the arrow function notation and didn't realise that it has to be ()=>{...return ...} . (Yep I should read the docs more carefully) I will leave this post here in case any future Googlers need it. Thanks for everyone's answer.
I want to implement search box from my set of props data .
I tried to follow this article https://dev.to/iam_timsmith/lets-build-a-search-bar-in-react-120j but i guess i m doing some silly mistakes.
any help to correct my mistake would be helpful for me.
//allbook.js
class AllBook extends Component {
constructor(props){
super(props);
this.state = {
search : ""
}
}
updateSearch(e){
this.setState({search: e.target.value.substr(0, 20)});
}
render(){
let filteredBooks = this.props.posts.filter(
(posts) => {
return posts.title.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
return(
<div>
{Object.keys(filteredBooks).length !== 0 ? <h1 className="post-heading">All books</h1> : <h1 className="post-heading">No Books available</h1>} {/*To check if array is empty or not*/}
{Object.keys(filteredBooks).length !== 0 ?
<input className="post-heading" type="text" value={this.state.search} onChange={this.updateSearch.bind(this)}/> : ""}
{/*Arrow function to map each added object*/}
{filteredBooks.map((post) =>(
<div key={post.id}>
{post.editing ? <EditComponent post={post} key={post.id}/> :
<Post key={post.id} post={post}/>}
</div>
))}
</div>
);
}
}
const mapStateToProps = (state) => {
return{
posts: state
}
}
export default connect(mapStateToProps)(AllBook);
Your updated code seems to be pretty close. I think you might experience a problem with using indexOf() though, since that will only find the index of a single-character within a string (title). This would not be good for multi-character searches (like full-words).
Try using .includes() instead so that you can at least search against complete words and titles. It's essentially a better version of .indexOf()
See sandbox for example: https://codesandbox.io/s/silly-currying-3zpvk
Working code:
class AllBook extends Component {
constructor(props){
super(props);
this.state = {
search : ""
}
}
updateSearch(e){
this.setState({search: e.target.value.substr(0, 20)});
}
render(){
let filteredBooks = this.props.posts.filter(
(posts) => {
return posts.title.toLowerCase().includes(this.state.search.toLowerCase());
}
);
return(
<div>
{Object.keys(filteredBooks).length !== 0 ? <h1 className="post-heading">All books</h1> : <h1 className="post-heading">No Books available</h1>} {/*To check if array is empty or not*/}
{Object.keys(filteredBooks).length !== 0 ?
<input className="post-heading" type="text" value={this.state.search} onChange={this.updateSearch.bind(this)}/> : ""}
{/*Arrow function to map each added object*/}
{filteredBooks.map((post) =>(
<div key={post.id}>
{post.editing ? <EditComponent post={post} key={post.id}/> :
<Post key={post.id} post={post}/>}
</div>
))}
</div>
);
}
}
const mapStateToProps = (state) => {
return{
posts: state
}
}
export default connect(mapStateToProps)(AllBook);
Updated code which is workable react search.
I started a chat project in react native. And now I'm having a problem with showing emoji. I got data of message, extract it and save to array. This is an example of message and the array of it
abc :smile: xyz
[
<Text>abc </Text>,
<Image source={{uri:"SMILE_EMOJI_URL"}} />
<Text> xyz</Text>
]
I will create a Text tag and put them all in as nested tags, so I just need to format one time. My expected result
<Text style={MY_STYLE}>
<Text>abc </Text><Image source={{uri:"SMILE_EMOJI_URL"}} /><Text> xyz</Text>
</Text>
How can I do it? Thank you!
your text-Component could look like this:
class ChatMessage extends React.Component {
constructor() {
super();
this.state = {
message: ""
}
}
componentWillMount() {
var localMessage;
for (let i = 0; i < arrayOfEmojiCodes.length; i++) {
if (this.props.message.includes(arrayOfEmojiCodes[i])) {
localMessage = this.props.message.split(arrayOfEmojiCodes[i])[0] + " <img src='"+arrayOfIconImages[arrayOfEmojiCodes[i]]+"' /> " + this.props.message.split(arrayOfEmojiCodes[i])[1];
i = arrayOfEmojiCodes.length;
} else {
localMessage = this.props.message;
}
}
this.setState({message: localMessage});
}
render() {
return(
<div className={this.props.style}>
<p>{this.state.message}</p>
</div>
);
}
}
then you can just call it:
<div className="chat">
{['Message1 :smile', 'message2'].map((value, index) => {
<ChatMessage key={index} message={value} />
})}
</div>
You need to do some modification to your code to fit it your needs, but basically this should make it easier to handle the situation.
I am new to react and have started following through the book learning react by Alex Banks and Eve Porcello. I have got to a section that creates a star rating system but at the moment I cant get it working can anyone tell me why? As far as I can tell I have copied the code correctly and everything looks like it should work as intended. Here is the code I have:
const Star = ({ selected=false, onClick=f=>f }) =>
<div className={ (selected) ? "star selected" : "star" } onClick={onClick}>
</div>
Star.propTypes = {
selected: PropTypes.bool,
onClick: PropTypes.func
}
class StarRating extends React.Component {
constructor(props) {
super(props)
this.state = { starsSelected: 0 }
this.change = this.change.bind(this)
}
change(starsSelected) {
this.setState({ starsSelected: starsSelected })
}
render() {
const { totalStars } = this.props
const { starsSelected } = this.state
return(
<div className="star-rating">
{[...Array(totalStars)].map((n,i) =>
<Star
key={i}
selected={i<starsSelected}
onClick={() => this.change(i+1)}
/>
)}
<p>{starsSelected} of {totalStars} stars</p>
</div>
)
}
}
StarRating.propTypes = {
totalStars: PropTypes.number
}
StarRating.defaultProps = {
totalStars: 5
}
When inspecting the components in react-dev-tools it seems that the stars selected prop is always set to false and I cant figure out why. Thanks for any help anyone can offer
It can be 2 things:
this line: {[...Array(totalStars)].map((n,i) =>
You need to pass totalStars as a Number and not a string:
<StarRating totalStars={5} />
or
you are not display anything in your Star component. Try this:
const Star = ({ selected = false, onClick = f => f }) => (
<div className={selected ? "star selected" : "star"} onClick={onClick}>
Star
</div>
);
See a working example:
https://codesandbox.io/s/52ox6wmwwk
The code shared is perfectly fine. Just render something from this code on which the click event would be fired.
const Star = ({ selected=false, onClick=f=>f }) =>
<div className={ (selected) ? "star selected" : "star" } onClick={onClick}>
// Something to render maybe?
</div>
Inject : npm i star-based-rating directly.
For Reference on this react package: star-based-rating
import { FaStar } from "react-icons/fa";
const CreateArray = (length) => [...Array(length)]; // This will create Array with the length provided.
// Star Component
function Star({ selected = false, onSelect }) {
return (
<FaStar color={selected ? "orange" : "lightgray"} onClick={onSelect} />
);
}
// Star Rating component
function StarRating({ totalStars = 5 }) {
const [selectedStars, setSelectedStars] = useState(0);
return (
<>
{CreateArray(totalStars).map((n, i) => (
<Star
key={i}
selected={selectedStars > i}
onSelect={() => setSelectedStars(i + 1)}
/>
))}
<p>
{selectedStars} of {totalStars} // To display selected stars out of total stars
</p>
</>
);
}
function App() {
return <StarRating totalStars={5} />; // This will display 5 stars
}
Working example - Star Rating - CodeSandbox
Your code is working absolutely fine. Check out this link : https://codesandbox.io/s/01wqmzrpjl
Make sure while declaring css classes star is above selected else it will not show the selected style fields if it has same style-field in star className.
Example in my link if I declare selected class above star class then red background (selected style property) is override by grey background (star style property).
I have an accordion in React formed of a row component which is looped inside a body parent component. In the row I'm toggling the state showDetails to show/hide the details for each row, effectively opening the accordion item. But, since the state is for each row, how do I close one accordion item when I open another one?
Body:
export default class Body extends React.Component {
render() {
const {modelProps, showInfo, linkedRow} = this.props;
return (
<div className="c-table__body">
{this.props.model.map(
(subModel, i) =>
linkedRow ?
<LinkedRow
key={`${i}`}
model={subModel}
modelProps={modelProps}
/>
:
<Row
key={`${i}_${subModel.username}`}
model={subModel}
modelProps={modelProps}
showInfo={showInfo}
handleStatusChanged={this.props.handleStatusChanged}
/>
)}
</div>
);
}
}
Row:
class Row extends React.Component {
constructor(props) {
super(props);
this.state = {
userId: '',
showDetails: false,
showModal: false,
status: '',
value: '',
showInfo: false
};
render() {
const { model, modelProps, showInfo } = this.props;
return (
<div className="c-table__row">
<div className="c-table__row-wrapper">
{modelProps.map((p, i) => (
<div className={`c-table__item ${this.isStatusCell(model[p]) ? model[p] : p}`} key={i}>{this.isStatusCell(model[p]) ? this.toTitleCase(model[p]) : model[p]}</div>
))}
{showInfo ? (
<div className="c-table__item c-table__item-sm">
<a
name="view-user"
onClick={this.showDetailsPanel}
className={this.state.showDetails ? 'info showing' : 'info'}
>
<Icon yicon="Expand_Cross_30_by_30" />
</a>
</div>
) : (
''
)}
</div>
{this.state.showDetails ? (<ConnectedDetails user={model} statusToggle={this.handleStatusChange}/>) : null}
</div>
);
}
}
export default Row;
Not really sure how to approach this, maybe something in the body that check is there's any row open according to the showDetails state in the rows?
Thanks in advance
The approach is to lift the state of which <Row /> is open to the <Body /> component.
Also the method that switch between opened <Row /> is on the <Body /> component.
toggleOpen = (idx) => {
this.setState({ openRowIndex: idx });
}
then when you rendered your <Row />s you can pass a prop isOpen:
<Row
key={`${i}_${subModel.username}`}
model={subModel}
modelProps={modelProps}
showInfo={showInfo}
handleStatusChanged={this.props.handleStatusChanged}
isOpen={this.state.openRowIndex === i}
onToggle={_ => this.toggleOpen(i)}
/>