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);
};
Related
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
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 just meet a problem that could not load the CSS inside react function component with material UI. Though I fixed it, I am still curious about the reason.
In the beginning, I write something like this, where I put both makeStyles and useStyles inside the function component. Then, I find that the class name is correctly assigned to the element, but no css is loaded.
import makeStyles from "material-UI"
import styles from "styles.js"
export default function alertPage() {
const useStyles = makeStyles(styles);
const classes = useStyles();
const [alert, setalert] = React.useState();
const showAlert = () => {
setalert(<p className={classes.text}></p>)
}
return (
<button onClick={showAlert}></button>
{alert}
)
}
Then, I put makeStyles outside the function, everything works correctly.
import makeStyles from "material-UI"
import styles from "styles.js"
const useStyles = makeStyles(styles);
export default function alertPage() {
const classes = useStyles();
const [alert, setalert] = React.useState();
const showAlert = () => {
setalert(<p className={classes.text}></p>)
}
return (
<button onClick={showAlert}></button>
{alert}
)
}
Then, I tried this code putting both inside function component again, but return the HTML directly, which still works.
import makeStyles from "material-UI"
import styles from "styles.js"
export default function alertPage() {
const useStyles = makeStyles(styles);
const classes = useStyles();
return (
<p className={classes.text}></p>
)
}
Then, I check the react official site and find that they always put CSS outside the function component, but not getting any sentences mentioned that this is required or why.
My guess is that I misunderstand the scope of the const or how CSS is actually loaded in the browser. If anybody could tell me the reason, or which piece of knowledge I missed, like js, ts, react, or how the browser works?
Thanks!
From the Material UI docs, you should have something like the below:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
// Your styles
},
});
export default function Hook() {
const classes = useStyles();
// Rest of your code
}
If you have styles in a correctly formatted import, you should be able to add them directly in the makeStyles declaration:
const useStyles = makeStyles(styles)
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>
)
}
I have a navigation component that uses Link, IndexLink to render the navigation bar:
class Navigation extends Component {
renderLinks = (linksData) => {
return linksData.map((link) => {
if(link.to === '/') {
return (
<li key={link.text}>
<IndexLink to={link.to}>
<i>{link.icon}</i>
<span>{link.text}</span>
</IndexLink>
</li>
);
} else {
return (
<li key={link.text}>
<Link to={link.to}>
<i>{link.icon}</i>
<span>{link.text}</span>
</Link>
</li>
);
}
});
};
render() {
const {links} = this.props;
return(
<div>
<ul>
{this.renderLinks(links)}
</ul>
</div>
)
}
}
Navigation.propTypes = {
links: React.PropTypes.array.isRequired
}
export default Navigation;
Now I want to test that my links render correcttly:
import React from 'react';
import {Link, IndexLink} from 'react-router';
import {mount} from 'enzyme';
import Navigation from '../components/core/Navigation.component';
describe('<Navigation/>', () => {
it('should render Navigation links', () => {
const links = [
{
to: '/',
icon: 'hourglass_empty',
text: 'Timer'
}
];
const navigation = mount(<Navigation links={links}/>);
console.log(navigation.find('a').prop('href'));
});
});
But this just logs out undefined. How am I able to test that the correct href value is getting passed to my anchors?
try this:
wrapper.find(Foo).at(0).props().href
This question is related to React, but for Vue, the following code works:
wrapper.find('.link').attributes('href')
The link has a prop of to in React to query the link find it by the text you click - and the right attribute is to not href
eg:
const url1 = screen.getByText("I am a link click me")
expect(url1).toHaveAttribute("to", "https://test-url1#")