I am trying to figure out a way to change the styling of multiple words each wrapped in a Text component in React Native, using an onPress event on each word.
I know how to do this in vanilla Javascript by running .split(" ") on a string to separate the words, and then mapping through them and wrapping them all in HTML elements like span tags with the word (in lowercase) as the class name and adding an onclick event that passes in the word .toLowerCase() as an argument to a function, which adds the word to an array of highlighted words, and then toggles adding or removing a class which will result in changing the styling of each instance of that word in a page.
The function would be something like this:
function exampleFunction(theWord) {
let temp = document.getElementsByClassName(theWord)
for (i = 0; i < temp.length; i ) {
if (temp[i].classList.contains("highlighted")) {
if (i === 0) {
let filteredArray = highlightedWords.filter((e) => e !== theWord)
highlightedWords = filteredArray
}
temp[i].classList.remove("highlighted")
} else {
if (i === 0) {
highlightedWords.push(theWord)
}
temp[i].classList.add("highlighted")
}
}
}
But the problem is that React Native doesn't seem to use classes. And I am very new to React Native. So I am lost as to how to approach this issue.
Any help is greatly appreciated.
CodePudding user response:
React uses a declarative instead of an imperative API as used in the DOM.
Therefore you should declare state which is the index of currently highlighted word (you can use a negative value to indicate that no word is highlighted). Then add the class highlighted
only when the index
of the word and the index in your state match. If one clicks on the same value again set the highlighted
to a negative value again. React will automatically re-re-render whenever you update the state using setHighlighted()
.
const Sentence = ({ words }) => {
const [highlighted, setHighlighted] = React.useState(-1);
return (
<React.Fragment>
{words.map((word, index) => (
<p key={word}
onClick={() => setHighlighted(highlighted === index ? -1: index)}
className={index === highlighted && "highlighted"}
>
{word}
</p>
))}
</React.Fragment>
);
};
ReactDOM.render(<Sentence words={["some ", "random ", "words."]}/>, document.getElementById('root'));
.highlighted {
color: blue;
background: red;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="root"></div>
CodePudding user response:
For react native , umm you cant do like that.
https://snack.expo.dev/ug8zEbrWZ
Please check working example above, and also do check out code here
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i ) {
color = letters[Math.floor(Math.random() * 16)];
}
return color;
}
export default function App() {
const [fC,setFc] = React.useState(getRandomColor())
const [sC,setSc] = React.useState(getRandomColor())
const [tC,setTc] = React.useState(getRandomColor())
const [zC,setZc] = React.useState(getRandomColor())
return (
<View style={styles.container}>
<View style={{flexDirection:'row'}}>
<Text
onPress={() => setFc(getRandomColor())}
style={[styles.eachStyle,{
color:fC
}]} >hey</Text>
<Text
onPress={() => setSc(getRandomColor())}
style={[styles.eachStyle,{
color:sC
}]}>this</Text>
<Text
onPress={() => setTc(getRandomColor())}
style={[styles.eachStyle,{
color:tC
}]}>is</Text>
<Text
onPress={() => setZc(getRandomColor())}
style={[styles.eachStyle,{
color:zC
}]}>great</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
eachStyle:{
marginHorizontal:3
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});