I would like to keep the background-color and color of the current clicked list item. I have made it to be highlighted via CSS with the following code:
.segmentsList:hover {
background: black;
color: white;
cursor: pointer;
}
I have tried to attach an onClickFunction to the onClick event inn the li as follows:
import React, {Component} from 'react';
import Link from "react-router-dom/es/Link";
import {Button} from 'reactstrap';
import cabeza from '../atlas/json/cabeza.json';
const parte = getParameterByName('parte') || 0;
export default class SegmentsList extends Component {
onClickFunction(e) {
console.log(e);
// e.target.element.class="newBlackColor";
}
render() {
console.log(cabeza[parte].etiquetas);
readTextFile(cabeza[parte].etiquetas);
function readTextFile(url) {
const rawFile = new XMLHttpRequest();
rawFile.open("GET", url, false);
rawFile.overrideMimeType('text/xml; charset=iso-8859-1');
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
const text = rawFile.responseText;
// console.log(rawFile.responseText);
const lines = splitLines(text);
// console.log(lines);
const words = splitWords(lines[0]);
// console.log(words);
window.words = words;
}
return;
function splitLines(text) {
return text.split('\n');
}
function splitWords(line) {
return line.split('" "').slice(1);
}
};
rawFile.send();
}
return (
<div>
<ol>
{window.words.map((word, index) =>
<li
onClick={this.onClickFunction}
className='segmentsList'
key={index}>{word}</li>
)}
</ol>
<Button
color='primary'
className='mt-3 ml-3'
>
<Link to='/'/>
Volver a la portada
</Button>
</div>
);
}
}
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
When I click on the list item, the console says:
Uncaught TypeError: Cannot set property 'class' of undefined
And inspecting the event object we see that the target is null:
target:null
What am I doing wrong?
I have also read:
CSS Change List Item Background Color with Class
How to give a different color to a selected list item with CSS?
Highlight item onClick - React.js
EDIT:
I would like to highlight the clicked one and remove the highlight of the previous clicked one.
I have written a way to highlight the list element and keep it highlighted until you clicked on it again:
SegmentsList.js
import React, {Component} from 'react';
import Link from "react-router-dom/es/Link";
import {Button} from 'reactstrap';
import cabeza from '../atlas/json/cabeza.json';
import SegmentsListItem from "./SegmentsListItem";
const parte = getParameterByName('parte') || 0;
export default class SegmentsList extends Component {
constructor(props) {
super(props);
}
render() {
console.log(cabeza[parte].etiquetas);
readTextFile(cabeza[parte].etiquetas);
function readTextFile(url) {
const rawFile = new XMLHttpRequest();
rawFile.open("GET", url, false);
rawFile.overrideMimeType('text/xml; charset=iso-8859-1');
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
const text = rawFile.responseText;
// console.log(rawFile.responseText);
const lines = splitLines(text);
// console.log(lines);
const words = splitWords(lines[0]);
// console.log(words);
window.words = words;
}
return;
function splitLines(text) {
return text.split('\n');
}
function splitWords(line) {
return line.split('" "').slice(1);
}
};
rawFile.send();
}
return (
<div>
<ol>
{window.words.map((word, index) =>
<SegmentsListItem word={word} key={index}/>
)}
</ol>
<Button
color='primary'
className='mt-3 ml-3'
>
<Link to='/'/>
Volver a la portada
</Button>
</div>
);
}
}
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
SegmentsListItem.js
import React, {Component} from 'react';
class SegmentsListItem extends Component {
constructor(props) {
super(props);
this.state = {highlighted: false};
}
highlight = (e) => {
console.log(e.target.className);
if (!this.state.highlighted) {
console.log('highlight');
e.target.className = 'segmentsListSelected';
} else {
console.log('remove highlight');
e.target.className = 'segmentsList';
}
this.setState({highlighted: !this.state.highlighted})
};
render() {
return (
<li
onClick={this.highlight}
className='segmentsList'
key={this.props.index}>{this.props.word}</li>
);
};
}
export default SegmentsListItem;
Thank you for your help.
I would like to keep the background-color and color of the current clicked list item. I have made it to be highlighted via CSS with the following code:
.segmentsList:hover {
background: black;
color: white;
cursor: pointer;
}
I have tried to attach an onClickFunction to the onClick event inn the li as follows:
import React, {Component} from 'react';
import Link from "react-router-dom/es/Link";
import {Button} from 'reactstrap';
import cabeza from '../atlas/json/cabeza.json';
const parte = getParameterByName('parte') || 0;
export default class SegmentsList extends Component {
onClickFunction(e) {
console.log(e);
// e.target.element.class="newBlackColor";
}
render() {
console.log(cabeza[parte].etiquetas);
readTextFile(cabeza[parte].etiquetas);
function readTextFile(url) {
const rawFile = new XMLHttpRequest();
rawFile.open("GET", url, false);
rawFile.overrideMimeType('text/xml; charset=iso-8859-1');
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
const text = rawFile.responseText;
// console.log(rawFile.responseText);
const lines = splitLines(text);
// console.log(lines);
const words = splitWords(lines[0]);
// console.log(words);
window.words = words;
}
return;
function splitLines(text) {
return text.split('\n');
}
function splitWords(line) {
return line.split('" "').slice(1);
}
};
rawFile.send();
}
return (
<div>
<ol>
{window.words.map((word, index) =>
<li
onClick={this.onClickFunction}
className='segmentsList'
key={index}>{word}</li>
)}
</ol>
<Button
color='primary'
className='mt-3 ml-3'
>
<Link to='/'/>
Volver a la portada
</Button>
</div>
);
}
}
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
When I click on the list item, the console says:
Uncaught TypeError: Cannot set property 'class' of undefined
And inspecting the event object we see that the target is null:
target:null
What am I doing wrong?
I have also read:
CSS Change List Item Background Color with Class
How to give a different color to a selected list item with CSS?
Highlight item onClick - React.js
EDIT:
I would like to highlight the clicked one and remove the highlight of the previous clicked one.
I have written a way to highlight the list element and keep it highlighted until you clicked on it again:
SegmentsList.js
import React, {Component} from 'react';
import Link from "react-router-dom/es/Link";
import {Button} from 'reactstrap';
import cabeza from '../atlas/json/cabeza.json';
import SegmentsListItem from "./SegmentsListItem";
const parte = getParameterByName('parte') || 0;
export default class SegmentsList extends Component {
constructor(props) {
super(props);
}
render() {
console.log(cabeza[parte].etiquetas);
readTextFile(cabeza[parte].etiquetas);
function readTextFile(url) {
const rawFile = new XMLHttpRequest();
rawFile.open("GET", url, false);
rawFile.overrideMimeType('text/xml; charset=iso-8859-1');
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
const text = rawFile.responseText;
// console.log(rawFile.responseText);
const lines = splitLines(text);
// console.log(lines);
const words = splitWords(lines[0]);
// console.log(words);
window.words = words;
}
return;
function splitLines(text) {
return text.split('\n');
}
function splitWords(line) {
return line.split('" "').slice(1);
}
};
rawFile.send();
}
return (
<div>
<ol>
{window.words.map((word, index) =>
<SegmentsListItem word={word} key={index}/>
)}
</ol>
<Button
color='primary'
className='mt-3 ml-3'
>
<Link to='/'/>
Volver a la portada
</Button>
</div>
);
}
}
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
SegmentsListItem.js
import React, {Component} from 'react';
class SegmentsListItem extends Component {
constructor(props) {
super(props);
this.state = {highlighted: false};
}
highlight = (e) => {
console.log(e.target.className);
if (!this.state.highlighted) {
console.log('highlight');
e.target.className = 'segmentsListSelected';
} else {
console.log('remove highlight');
e.target.className = 'segmentsList';
}
this.setState({highlighted: !this.state.highlighted})
};
render() {
return (
<li
onClick={this.highlight}
className='segmentsList'
key={this.props.index}>{this.props.word}</li>
);
};
}
export default SegmentsListItem;
Thank you for your help.
Share Improve this question edited Jun 8, 2018 at 23:12 Yone asked Jun 8, 2018 at 22:27 YoneYone 2,1347 gold badges31 silver badges61 bronze badges 2- 1 I originally submitted an answer but there is too much wrong here. You are not properly using react here and that is a bigger problem. – Deadron Commented Jun 8, 2018 at 23:00
- Hi, just to clarify you want to keep the list item highlighted? I agree with Deadron you aren’t using react for what it’s made for. I would use inline styling and set the colors using the ponents state. If you don’t have it figured out by tonight I’ll answer it with a working sample. – sonic_ninja Commented Jun 8, 2018 at 23:08
1 Answer
Reset to default 5You aren't using React correctly and I would HIGHLY remend you spend some time reading the docs on how a ponent should be used. That being said, in this instance you should use state to store the words that get loaded and also for an active selection. Also DONT I repeat DONT open a file in the render method!... render cycles can happen a lot and that would mean you open the file every time render happens, which is a bad idea.
// these are more helper functions.. either define them on your class or just define them in a helpers/utility file. or just put as a global above the class
function splitLines(text) {
return text.split('\n');
}
function splitWords(line) {
return line.split('" "').slice(1);
}
export default class SegmentsList extends Component {
constructor(props) {
super(props);
this.state = { words: [], activeWord: -1 }
}
onClickFunction = (idx) => {
// set the state to only have a current word selection which will unselect the previous selection
this.setState({activeWord: idx})
}
readTextFile = (url) => {
const rawFile = new XMLHttpRequest();
rawFile.open("GET", url, false);
rawFile.overrideMimeType('text/xml; charset=iso-8859-1');
rawFile.onreadystatechange = () => {
if (rawFile.readyState === 4) {
const text = rawFile.responseText;
const lines = splitLines(text);
const words = splitWords(lines[0]);
this.setState({words});
}
return;
};
rawFile.send();
}
ponentDidMount() {
this.readTextFile(cabeza[parte].etiquetas);
}
render() {
return (
<div>
<ol>
{this.state.words.map((word, index) =>
<li
onClick={this.onClickFunction.bind(null, index)}
className={`segmentsList${this.state.activeWord === index ? ' selected' : ''}`}
key={index}
>
{word}
</li>
)}
</ol>
<Button
color='primary'
className='mt-3 ml-3'
>
<Link to='/'/>
Volver a la portada
</Button>
</div>
);
}
}
then the last thing is to add a class for the selection in your css
.segmentsList:hover, .segmentsList.selected {
background: black;
color: white;
cursor: pointer;
}