React - Having trouble onClick (React) - javascript

((New to React))
I am trying to get the different jobs (salary.job.id listed above) to pass through on click. The jobs are already being obtained through an axios call.
Is there an easier way to accomplish this? Also, is it correct to call the this.makesalary twice (once in componentDidMount and another through the click?
This is what i am trying to pass through
makesalary(slug = "charlotte") {
axios.get(`https://api.teleport.org/api/urban_areas/slug:${slug}/salaries/`)
.then(results => {
console.log(results)
const filteredata = results.data.salaries.filter(salary=>{
if(salary.job.id === "UX-DESIGNER"){
return true
}
if (salary.job.id === "WEB-DEVELOPER"){
return true
}
if(salary.job.id === "MOBILE-DEVELOPER"){
return true
}
return false
})
this.setState({salaries:
filteredata
})
}
)
}
Can this be called twice? and is the placement correct?
componentDidMount (){
this.makesalary(this.props.slug)
}
_onclick(salary){
this.makesalary(salary.job.id)
}
Here is the render
<div>
<h2>What Tech Job are you in currently?</h2>
<CardGroup>
<Card>
<Card.Img variant="top" src= {Mobileicon} />
<Card.Body>
<Card.Title>Mobile Developer</Card.Title>
<Card.Text>
Mobile Developer specialise in mobile technology such as building apps for Google's Android, Apple's iOS and Microsoft's Windows Phone platforms.
</Card.Text>
</Card.Body>
<Card.Footer>
<Button variant="danger" onClick={this._onclick}>Pick this Job!</Button>{' '}
</Card.Footer>
</Card>
<Card>
<Card.Img variant="top" src= {UXicon} />
<Card.Body>
<Card.Title>UX Designer</Card.Title>
<Card.Text>
In a nutshell, the UX designer is responsible for how a product or website feels.
The UX designer's job is to zero in on users' underlying emotional and functional needs.
</Card.Text>
</Card.Body>
<Card.Footer>
<Button variant="danger" >Pick this Job!</Button>{' '}
</Card.Footer>
</Card>
<Card>
<Card.Img variant="top" src={Webdevelop} />
<Card.Body>
<Card.Title>Web Developer</Card.Title>
<Card.Text>
A Web Developer is responsible for the coding, design and layout of a website according to a company's specifications.
As the role takes into consideration user experience and function, a certain level of both graphic design and computer programming is necessary.
</Card.Text>
</Card.Body>
<Card.Footer>
<Button variant="danger" >
Pick this Job!</Button>{' '}
</Card.Footer>
</Card>
</CardGroup>
</div>
)
}

I'd like to help out so I'm going to point out a few things and also suggest a bit. Before starting, I have to apologize if something I say is incorrect and would appreciate it if someone would correct me on such.
I'm also going to assume that your makesalary function is defined above (where the Axios call is shown).
In your componentdidmount method, you call makesalary with the parameter you have obtained from props. If your props are valid, this is absolutely fine.
You also happen to call makesalary in the _onclick method. I'd suggest you rename it to something such as handleClick or onClickHandler to make it more clear, and remove the _ in front as it's unnecessary (unless it's a convention you are using). The method itself looks fine.
When you are calling _onclick with the button, keep in mind that it's going to pass an event into the method. You should handle this by either passing a function such as () => _onclick(salary) to onClick at the button (since you don't intend to use the event for anything). Aside from handling the event correctly, this also helps you to pass in the correct parameter for _onclick. In the code snippet you have provided, it seems that onClick is not passing any parameters to the _onclick function.
I'd recommend you to read up on the official React documentation regarding this:
https://reactjs.org/docs/handling-events.html.
Hope I've helped!
EDIT: In case you're wondering, it's absolutely okay to call the same method twice!

Related

Best way to change CSS in multiple components of the same component in React

I have a component that i'm using 3 times with different data which I am able to complete with the following code;
<div>
<Container className="mt-5">
<Row>
{author_data.map((authors) => {
return (
<Col key={authors.id} className="pe-5 ps-5">
<Author
key={authors.id}
image={authors.image}
author={authors.author}
description={authors.description}
handleClick={(author) => setAuthor(author)}
/>
</Col>
);
})}
</Row>
</Container>
</div>
);
However Im looking to change the CSS on each component once I click on one of the Author components. something like the below using native JS.
document.getElementById("author1").classList.add("addGrayScale");
document.getElementById("author2").classList.add("addGrayScale");
document.getElementById("author3").classList.remove("addGrayScale");
I have used the useState and useContext hooks but I can't seem to get it to work because the Author component will receive the same props. Should I create separate components for each Author? or is there another way to do this.

Menu does not collapse when you click on one of the menu items on Mobile Devices

Hi All i need some help :)
I working on a Gatsby, React portfolio where i have a problem with The Menu It does not collapse when you click on one of the menu items on Mobile Devices.
The menu is working fine on desktop.
The menu works fine on all devices until I installed the react-scroll package and set it up.
I have tried to search on Google for help and i found some simlare issues but i still dont know to fix the problem. :)
Hope you can help.
There is to Nav components i my project:
This my Project on SandBox:
NavBar.js
https://codesandbox.io/s/gatsby-starter-and-portfolio-jr9tn?file=/src/components/Navbar/Navbar.js
NavbarLinks:
https://codesandbox.io/s/gatsby-starter-and-portfolio-jr9tn?file=/src/components/Navbar/NavbarLinks.js
Here you have your CodeSandbox fixed: https://codesandbox.io/s/gatsby-starter-and-portfolio-forked-43thz?file=/src/components/Navbar/NavbarLinks.js
What was happening is that, since you've installed react-scroll, the state was never updated when an item was selected so, React's rehydration was never occurring and your menu was never closed. The code is a bit redundant however I've managed to get it to work. What I've added is a simple function passed via props that toggle the menu.
In your NavBar.js, instead of:
<Toggle
navbarOpen={navbarOpen}
onClick={() => setNavbarOpen(!navbarOpen)}
>
If added a function, since it's not a good practice to trigger effects directly bonded in the components. I've changed it to:
<Toggle navbarOpen={navbarOpen} onClick={toggleMenu}>
That toggleMenu function, is a simply function that does the same than your previous one:
const toggleMenu = () => setNavbarOpen(!navbarOpen)
Now, you have isolated that piece of functionality and you can reuse it, passing it to your child component (NavbarLinks):
{navbarOpen ? (
<Navbox>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
) : (
<Navbox open>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
)}
Note: this code is redundant, should be refactored to avoid that kind of unnecessary repetition. For example, something like this is much better:
<Navbox open={navbarOpen}>
<NavbarLinks toggleMenu={toggleMenu} />
</Navbox>
As you can see, you <NavbarLinks> have the functionality to toggle the menu in toggleMenu function so there you can trigger the function in every click (onClick):
const NavbarLinks = ({ toggleMenu })=> {
return (
<>
<NavItem
activeClass="active"
to="section1"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu}
>
About
</NavItem>
<NavItem
activeClass="active"
to="section2"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu}
>
Test
</NavItem>
<NavItem
activeClass="active"
to="section3"
spy={true}
smooth={true}
duration={1000}
onClick={toggleMenu)}
>
Gallery
</NavItem>
<NavItem to="/page-2">Contact</NavItem>
</>
)
}
Since you are destructuring props, you have the toggleMenu function available directly.

Making a react component clickable

I have a functional REACT component, code is as follows
const MobileListing = (props) => {
function handleClick() {
console.log('in cardClick');
}
return (
<div>
<Row>
<Card onClick={() => handleClick()} style={{cursor : 'pointer'}} >
<Card.Img variant="top" src="holder.js/100px180" />
<Card.Body>
<Card.Title>Card Title</Card.Title>
<Card.Text>
Some quick example text to build on the card title and make up the bulk of
the card's content.
</Card.Text>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
</Row>
</div>
);
}
export default MobileListing;
I want to make the entire card clickable. I read through a post on stack overflow Making whole card clickable in Reactstrap which talks about using an anchor tag, but that doesn't work for me.
Can someone help me understand what I am doing wrong?
A card looks like this on my site and I want to make the whole card clickable.
You can use the onClick either on the top-level div element for this, or, in case there would be more cards inside the Row you can wrap each with a div and give it the onClick, property.
such like:
<div>
<Row>
<div onClick={handleClick}>
<Card style={{ width: '18rem', cursor : 'pointer' }} >
<Card.Img variant="top" src="holder.js/100px180" />
<Card.Body>
<Card.Title>Card Title</Card.Title>
<Card.Text>
Some quick example text to build on the card title and make up the bulk of
the card's content.
</Card.Text>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
</div>
</Row>
</div>
It is better to wrap it around with an anchor tag because clickable things should be links if they go to places, and should be buttons if they do things.
Using click handlers with other things just make things inaccessible.

Updating child props value on parent props value change

guys! I'm building React Native component that contains a UI pattern. This UI pattern will contain several smaller reusable patterns. This way:
<ListItem onPress={}>
<IconContainer>
<Icon />
</IconContainer>
<Body>
<Text>Content</Text>
</Body>
<Right>
<Action onPress={} />
</Right>
<ListItem>
Now I'm also building embedding size variants (small, medium/default and large) for some of these children, like this for example:
<IconContainer large={boolean} small={boolean}>
<Icon />
</IconContainer>
And since the are several children, I don't want to have the person using the component to have to specify the size variant for each one of the children. That'll also require them to know which one of the children have size variants and which one doesn't.
So, what I'm trying to do is to embed a props.large and a props.small into the parent and use that to change de value of the same prop if available in the children.
Any ideas of how to do that in a simple way?
(I suspect this is easy but I've been struggling with this for a while so I thought I'd ask for some help.)
Thanks in advance!

rendering an additional pop up dialog on button click React

I am having issues with rendering a pop up loading screen. So assume i have a imported component called ( LoadingDialog ) and i want it to render when the state property, loading is true. When the user clicks a button on the current component, it triggers an api call which also changes the loading state to true, thus rendering the loading dialog.
I understand I can use conditional rendering to achive this, eg:
if(this.state.loading){
return (
<div>
<LoadingDialog />
</div>
)
}
else{
return(
<div> OTHER UI ELEMENTS </div>
)
but now i have a problem because, when my loadingDialog is rendered, my other ui (text area, background card, button ) all disappear, which is the opposite of what im trying to achieve. With this approach, i can only display my actual ui elements or the loading dialog.
I've tried separating the other ui elements into a separate container but it doesn't help as i need to call the api on click of an button and the entire problem i'm having now occurs in that child container.
I've also tried the above approach with passing a parent on click method as a prop and calling that when the button is clicked but somehow ended up with a recursive loop of the parent/child component
Heres my actual code:
if(this.state.loading){
return (
<div>
<LoadingDialog />
</div>
)
}
else{
return (
<div>
<Card className="center card">
<div className="row">
<div class="column" >
<TextField
id="outlined-name"
name="searchContent"
onChange={this.handleChange}
value={this.state.searchContent}
label="Name"
variant="outlined"
/>
</div>
<div className="column">
<Button
variant="outlined"
color="primary"
onClick={this.handleClick}
>
Search
</Button>
</div>
</div>
</Card>
</div>
);
}
and this is my handle click function:
handleClick = (event, name) => {
this.setState({loading : true})
fetch(uri)
.then(res => res.json())
.then(data => {
console.log(data);
this.setState({loading : false})
});
};
As i said before, I tried separating the UI bit on the else block to a different component but the problem still persisted. To summarise it again,
I can only render my actual ui or a popup box but not both at any given time.
I want to be able to render both at the same time, if needed.
I am very new to react and staying away from the likes of redux, hooks etc.
SOLVED Thanks to Chris G
So the issue was easily fixed by using a logical and operator to check if loading is true or false, like so {this.state.loading && <LoadingDialog />}
eg.
render(){
return(
<div>
{this.state.loading && <LoadingDialog />}
<div>
//REST OF THE STUFF THAT SHOULD BE RENDERED REGARDLESS
</div>
</div>
)
}

Categories

Resources