On React, I attempted making a feature to let user can see active feedback on screen by changing its icon when they click it.
How can I let it change to another icon (e.g. from Box to BoxChecked) once I click it?
note: I know this code line is the problem...(sob)
<img src={click} alt="icon" onClick={handleClick} />
App.jsx
import React, { useState } from 'react'
import './App.css'
import { GrCheckbox as Box } from 'react-icons/gr'
import { GrCheckboxSelected as BoxChecked } from 'react-icons/gr'
export default function App() {
const [icon, setIcon] = useState(false);
const [click, setClick] = useState(Box);
function handleClick() {
setIcon(!icon);
icon ? setClick(Box) : setClick(BoxChecked);
}
return (
<div className="App">
<img src={click} alt="icon" onClick={handleClick} />
<p>Clicked {click} times</p>
</div>
);
}
Storing a component in state is not recommended. Use condition to set src.
<img src={icon ? Box : BoxChecked} alt="icon" onClick={handleClick} />
Change handler to this
function handleClick() {
setIcon(prevIcon => !prevIcon);
}
or better
const handleClick = useCallback(() => {
setIcon(prevIcon => !prevIcon);
}, []);
useState is async so you don't have the value of icon immediately after the execution of setIcon in your handler.
You need to put the setClick call in a useEffect hook:
React.useEffect(() => {
icon ? setClick(Box) : setClick(BoxChecked);
}, [icon]);
function handleClick() {
setIcon(!icon);
}
This effect will be executed when icon changes because it is added to the useEffect's dependency array. Have a look at the docs for more info:
https://reactjs.org/docs/hooks-effect.html
Related
I'm trying to learn ReactJS and now I'm making a small project that consists of a button that every time I click it, it will show an html element (as I still couldn't get the button to work, I haven't created the element yet, so the element it should create is an h1), but when I click the button nothing happens, could anyone help me? (sorry for any spelling mistakes, I'm still learning English)
This is my code:
import Container from "./App.style";
import Button from "./Components/Button/Button.jsx";
const App = () => {
const createElement = () => {
return(
<h1>Hey</h1>
)
}
return (
<>
<Container>
<h1>Criador De Elementos</h1>
<Button onClick={ createElement }>Criar Elemento</Button>
</Container>
</>
);
}
export default App;
import React from "react";
import StylesButton from "./Button.style";
const Button = ( {onClick, children} ) => {
return (
<StylesButton onClick={ onClick }> { children } </StylesButton>
);
}
export default Button;
Looks like you your code is correct. But my question is where you want to that h1 element. If you want h1 to Your DOM than you must create an h1 to your DOM and control value of h1 by using state (by Using useState Hook).
if you want to render your h1 element then you can do like this.
import {useState} from 'react';
import Container from "./App.style";
import Button from "./Components/Button/Button.jsx";
const App = () => {
const [heading,setHeading] = useState("");
const createElement = () => {
setHeading("Hey");
}
return (
<>
<Container>
<h1>Criador De Elementos</h1>
<Button onClick={ createElement }>Criar Elemento</Button>
<h1>{heading}</h1>
</Container>
</>
);
}
export default App;
import React from "react";
import StylesButton from "./Button.style";
const Button = ( {onClick, children} ) => {
return (
<StylesButton onClick={ onClick }> { children } </StylesButton>
);
}
export default Button;
I've been working on this dropdown menu for a while but I can't seem to get the dropdown menu to change the page I'm on and I don't understand what's wrong with it I am really new to ReactJs, I have a module called DropDownMenu it is calling DropDownItem and when DropDownItem is clicked is called a function called handle click but in the HandleClick it is not switching the page to the current Props.Route clicked on and i don't know enough of whats going on to really figure it out
import React from "react";
import { Link } from "react-router-dom";
function DropdownItem(props) {
const handleClick = () => {
<Link to={props.route}></Link>;
console.log(props.route);
};
return (
<a href="#" className="menu-item" onClick={handleClick}>
<span className="icon-button">{props.leftIcon}</span>
<span className="Route">{props.route}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</a>
);
}
export default DropdownItem;
You can't just throw a <Link> in the middle of a callback function and expect it to do anything when called.
Use the <Link> element instead of the <a> element.
Make use of useNavigate if you need to trigger navigation from a callback (which you don't in this case).
You can use useHistory hook.you may use to navigate.
when you use react router dom v5
import { useHistory } from "react-router-dom";
let history = useHistory();
const handleClick = () => {
history.push(`/${props.route}`);
console.log(props.route);
};
when you use react router dom v5
import { useHistory } from "react-router-dom";
const navigate = useNavigate();
const handleClick = () => {
navigate(`../${props.route}`, { replace: true });
console.log(props.route);
};
i tried to build my webapp but i have a little problem the reason is because the verson the instructor is old verson but i updated to the latest verson i have this problem.
What I am trying to do is generate clicks into the post. But I can't click on it. When I open it, this error is what I'm getting.
Home.js:23 Uncaught TypeError: navigate.push is not a function
at onClick (Home.js:23:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
at invokeGuardedCallback (react-dom.development.js:4056:1)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070:1)
at executeDispatch (react-dom.development.js:8243:1)
at processDispatchQueueItemsInOrder (react-dom.development.js:8275:1)
at processDispatchQueue (react-dom.development.js:8288:1)
at dispatchEventsForPlugins (react-dom.development.js:8299:1)
at react-dom.development.js:8508:1
this is the code
import React from "react";
import axios from "axios";
import { useEffect, useState } from "react";
import { useNavigate } from 'react-router-dom';
function Home() {
const [listOfPosts, setListOfPosts] = useState([]);
const navigate = useNavigate();
useEffect(() => {
axios.get("https://my-project-ienpf.run-us-west2.goorm.io/posts").then((response) => {
setListOfPosts(response.data);
});
}, []);
return (
<div>
{listOfPosts.map((value, key) => {
return (
<div
className="post"
onClick={() => {
navigate.push(`/post/${value.id}`);
}}
>
<div className="title"> {value.title} </div>
<div className="body">{value.postText}</div>
<div className="footer">{value.username}</div>
</div>
);
})}
</div>
);
}
export default Home;
I hope you can help me
You can change
navigate.push(`/post/${value.id}`);
to
navigate(`/post/${value.id}`);
don`t do this, navigate = useNavigate();
navigate.push("/about")
instead, navigate("/about")
I want text entry to be highlighted with different colors depending on the character entered.
My hunch is that it is possible to do this by adding <span> elements with the appropriate styling inside of a contenteditable div.
Is there a better way?
Hi Please check this example. I used material-ui
import React, {useState} from 'react';
import Box from '#material-ui/core/Box';
import TextField from "#material-ui/core/TextField";
export default function BackgroundColor() {
const [text, setText] = useState('');
const [color, setColor] = useState('');
function changeHandler(event) {
setText(event.target.value);
if(event.target.value.toLowerCase() === 'a'){
setColor("primary.main");
}
else if(event.target.value.toLowerCase() === 'b'){
setColor("secondary.main");
}
else if(event.target.value.toLowerCase() === 'c'){
setColor("error.main");
}
else{
setColor("info.main");
}
}
return (
<div>
<TextField id="standard-basic" label="Standard" helperText="Type A or B or C" onChange={changeHandler} />
<Box color={color}>
{text}
</Box>
</div>
);
}
Depending on the complexity, you can also consider using Ace Editor
import React, { useState } from "react";
import AceEditor from "react-ace-builds";
import "./yamlHighlightRules";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/ace";
import "./styles.css";
export default function App() {
const [text, setText] = useState("This is the most amazing initial text.");
const handleChange = input => {
setText(input);
};
return (
<div className="App">
<AceEditor
mode="yaml"
theme="github"
name="editor"
fontSize={15}
showPrintMargin={true}
showGutter={false}
highlightActiveLine={false}
value={text}
onChange={handleChange}
setOptions={{
showLineNumbers: true,
tabSize: 2,
readOnly: false
}}
height={"600px"}
width={"100%"}
/>
</div>
);
}
And then I edited an existing set of yaml highlighting rules, it's easier not starting from scratch.
import ace from "ace-builds/src-min-noconflict/ace";
import "ace-builds/src-noconflict/mode-text";
ace.define("ace/mode/yaml_highlight_rules", [], function(require, exports) {
const oop = require("../lib/oop");
const TextHighlightRules = require("./text_highlight_rules")
.TextHighlightRules;
const YamlHighlightRules = function() {
this.$rules = {
start: [
{
token: "highlight",
regex: /amazing/
}
]
};
this.normalizeRules();
};
oop.inherits(YamlHighlightRules, TextHighlightRules);
exports.YamlHighlightRules = YamlHighlightRules;
});
The token is your css class. Just add the prefix ace_ to it. Then you define a regular expression to determine what gets that class.
.ace_highlight {
background-color: yellow;
}
Here is a codesandbox where you can see it working.
And here are the docs on defining your own modes.
I'm trying to load a JSON from AsyncStorage every time a user opens one of my react-native screens (I'm using StackNavigator). This JSON contains information on what my states should be set to.
How can I call a function that runs every time this screen is opened?
Further info:
I've written a function that updates my states according to a JSON loaded from AsyncStorage. The function works perfectly when called from a button, but when the function is called from render(), part of my screen freezes and some buttons are not touchable anymore. Strangely only TextInput still works.
use componentWillMount() method. This will execute automatically before render() method gets triggered.
class Sample extends Component{
state = {data : []};
componentWillMount(){
this.setState({data : inputObject});
}
render(){
return(
<View>
//you can render the data here
</View>
);
}
}
import { useEffect, useState } from 'react';
const Sample = () => {
const [state, setState] = useState([]);
useEffect(() => {
setState(inputObject);
}, [])
return(
<View>
//you can render the data here
</View>
);
}
Reference: https://facebook.github.io/react/docs/react-component.html#componentwillmount
If you want to handle back button page navigation then you need to listen to the
navigation event once when the component has mounted, use the code below for the same.
componentDidMount = () => {
this.focusListener = this.props.navigation.addListener('focus',
() => {
console.log('focus is called');
//your logic here.
}
);
}
This can be easily accomplished using 'withNavigationFocus' , found in the react native documentation here
import React, { Component } from 'react';
import { View } from 'react-native';
import { withNavigationFocus } from 'react-navigation';
class TabScreen extends Component {
componentDidUpdate(prevProps) {
if (prevProps.isFocused !== this.props.isFocused) {
// Use the `this.props.isFocused` boolean
// Call any action
}
}
render() {
return <View />;
}
}
// withNavigationFocus returns a component that wraps TabScreen and passes
// in the navigation prop
export default withNavigationFocus(TabScreen);
You could use a hook approach:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
I literally just copied the first example of the documentation, but it's a very good one.
If you want continue reading: https://reactjs.org/docs/hooks-effect.html
I used "onLayout" method inside the view.
read the doc
onLayout: Invoked on mount and on layout changes.
export default function Login({ navigation }) {
const executeOnLoad = () => {
console.log("view has loaded!");
};
return (
<View style={styles.container} onLayout={executeOnLoad}>
--- layout code here
</View>
);
}
Since you are dealing with the screen, I will suggest you use useFocusEffect hooks.
example:
const ExampleScreen = () => {
// your code here
useFocusEffect(useCallback(() => {
// your logic goes here
}, []))
return (
<View>
{/* render your content here */}
</View>
)
}