React UseState flow - javascript

in useStates, normally to set the color you would have to do setSelected(selected) to use that react hook, but it is never used like that below: How is setSelected being used so that it can change the color?
Is onSelectedChange a function that is equal to the function setSelected? A function receiving another function?
App.js
const options =[
{
label:'The color red',
value:'red'
},
{
label:'The color blue',
value:'blue'
},
{
label:'The color green',
value:'green'
}
];
export default () => {
const [selected, setSelected]=useState(options[0]);
return (
<div>
<Dropdown
selected={selected}
onSelectedChange={setSelected}
options = {options}/>
</div>
);
};
Dropdown.js
import React from 'react';
const Dropdown = ({options,selected, onSelectedChange})=>{
const renderedOptions = options.map((option)=>{
return (
<div key = {option.value}
className="item"
onClick={()=>onSelectedChange(option)}
>
{option.label}
</div>
)
});
return (
<div className="ui form">
<div className="field">
<label className="label">Select a color</label>
<div className="ui selection dropdown visible active">
<i className="dropdown icon"></i>
<div className="text">{selected.label}</div>
<div className="menu visible transition">
{renderedOptions}
</div>
</div>
</div>
</div>
);
};

It is passed to <Dropdown> component as onSelectedChange prop
<Dropdown
selected={selected}
onSelectedChange={setSelected}
options = {options}/>
Which is then invoked from the onClick handler onClick={()=>onSelectedChange(option)

Related

How to create "Selected tab" in Next.Js?

I am trying to create selected tab in Next.Js.
The User will have the option to search for data it can be Users or Posts, what the user will search for will be selected by clicking on one of the buttons.
Once the user clicks on the button the button will change background to blue.
However I can't make it to work properly, when the User clicks on the button the .Selected class gets added to the button but the button doesn't render the CSS.
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState < String > ();
const setSearchOption = (searchFor: String) => {
let searchOption = '';
if (searchFor == 'POSTS') {
searchOption = 'POSTS';
} else {
searchOption = 'USERS';
let button = document.getElementById('usersOption') as HTMLElement;
button.className += style.Selected;
}
console.log(searchOption);
setPostsSearch(searchOption);
}
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...' />
</div>
<div className={style.SearchOptions}>
<button id='usersOption' onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement) {
return (
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
you can use searchOption data for className style
import React, { MouseEventHandler, ReactElement, useState } from 'react'
import { PageWithLayout } from '../components/Layouts/LayoutConfig'
import MainLayout from '../components/Layouts/MainLayout'
import style from '../styles/Search.module.css'
const Search: PageWithLayout = () => {
const [searchPosts, setPostsSearch] = useState<String>();
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={searchPosts === 'USERS' ? style.Selected : undefined } onClick={() => setPostsSearch('USERS')}>Users</button>
<button id='postsOption' className={searchPosts === 'POSTS' ? style.Selected : undefined } onClick={() => setPostsSearch('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)
}
Search.getLayout = function getLayout(page: ReactElement){
return(
<MainLayout>
{page}
</MainLayout>
)
}
export default Search
Just have a state for active searchOption and apply the class conditionally directly into the JSX.
const [activeSearchOption, setActiveSearchOption] = useState('USERS')
return (
<>
<div className='pageContent'>
<div className={style.SearchBarContainer}>
<div className={style.SearchContainer}>
<i className="fa-solid fa-magnifying-glass"></i>
<input className={style.SearchBar} type={'text'} placeholder='Search...'/>
</div>
<div className={style.SearchOptions}>
<button id='usersOption' className={activeSearchOption === 'USERS' ? 'active' : ''} onClick={() => setSearchOption('USERS')}>Users</button>
<button id='postsOption' className={activeSearchOption === 'POSTS' ? 'active' : ''} onClick={() => setSearchOption('POSTS')}>Posts</button>
</div>
</div>
<div className='SearchedContent'>
</div>
</div>
</>
)

How to change props object name when it's clicked in react?

I'm creating a youtube clone using react js and i used this icon
import HomeIconfilled from '#mui/icons-material/Home';
import HomeIcon from '#mui/icons-material/HomeOutlined';
That looks like this HomeIconfilled
which gets rendered by calling this function
<Sidebariconfunc Icon={HomeIconfilled} Title="Home"/>
That takes 2 parameters and reder the icon
function Sidebariconfunc({Icon,Title}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
<Icon/>
</div>
<div className='Slidebar_Title'>
{Title}
</div>
</div>
)
}
How can i chane the props name to HomeIcon when i click on the icon so that it changes to this this icon HomeIcon
Thamks !
function SidebarIcon({ActiveIcon, InactiveIcon, title, isActive}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
{isActive ? <ActiveIcon/> : <InactiveIcon />
</div>
<div className='Slidebar_Title'>{Title}</div>
</div>
)
}
Usage:
const [isActive, setIsActive] = React.useState(false)
return (
<a onClick={() => setIsActive(!isActive)>
<SidebarIcon
ActiveIcon={HomeIconfilled}
InactiveIcon={HomeIcon}
title='Home'
isActive={isActive}
/>
</a>
)

Problem using a prop in functional component IT Says TypeError: onClick is not a function

im having problems trying to use the onclick function as props it sais when i clicked TypeError: onClick is not a function
What can i do!
7 | <Card
8 | onClick={() => onClick(dish.id)}>
| ^ 9 |
it is my first time using this kind of components
import React from 'react';
import { Card, CardImg, CardImgOverlay,
CardTitle } from 'reactstrap';
function RenderMenuItem ({dish, onClick}) {
return (
<Card
onClick={() => onClick(dish.id)}>
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
);
}
const Menu = (props) => {
const menu = props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<RenderMenuItem dish={dish} onClick={props.onClick} />
</div>
);
});
return (
<div className="container">
<div className="row">
{menu}
</div>
</div>
);
}
export default Menu;
Try to have default props to avoid run time errors.
const Menu = (props) => {
const menu = props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<RenderMenuItem dish={dish} onClick={props.onClick} />
</div>
);
});
return (
<div className="container">
<div className="row">{menu}</div>
</div>
);
};
Menu.defaultProps = {
dishes: [],
onClick: () => {},
};
You must now use Menu component by providing valid function. For example <Menu onClick={dishId => {/* Logic /*}}/>

React: Update component data/props after promise resolved

I'm a bit new to React and I've been having some problems understanding the workarounds of certain methods that I've used in other languages.
The Problem:
What I was hoping to achieve is that whenever the user clicks a button, the app will render a new section displaying some variable values. What I did was that when the user clicked a button, an state changed, and let the new Component render, and I passed the data through its props.
The problem is, If I understand correctly, that I'm passing the old values when I create the component and not the actual/updated values that I want to render...
Let's say I have this following variables.
const user_data = {
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...',
};
Those variables are going to change value whenever the user click a button.
This next block of code is what I use to render the next component where I want the new values.
const SomeComponent = props => {
const [resolved, setResolved] = useState({ display: false });
const displayValidation = props => {
setResolved({ ...resolved, display: !resolved.display });
};
function getData(username) {
const url = 'https://www.twitter.com/' + username;
getHTML(url)
.then(res => {
getUserData(res).then(res => {
user_data.followers = res.followers;
user_data.followings = res.followings;
user_data.nTweets = res.nTweets;
user_data.pic_url = res.pic_url;
console.log('Updated data:', user_data);
displayValidation();
});
})
.catch(function(error) {
console.error('Username was not found.');
});
}
const handleSubmit = event => {
event.preventDefault();
console.log('Resolving data...');
getData(user.username);
};
return (
<React.Fragment>
<Navbar />
<div className="container lg-padding">
<div className="row" id="getTracker">
<div className="col-sm-12 center">
<div className="card text-center hoverable">
<div className="card-body">
<div className="input-field">
<i className="material-icons prefix">account_circle</i>
<input
id="username"
type="text"
className="validate"
value={user.username}
onChange={handleChange}
/>
<label htmlFor="username">Enter a username to track</label>
</div>
<input
type="button"
onClick={handleSubmit}
value="Track"
className="btn-large blue darken-4 waves-effect waves-light"
/>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>
</div>
</div>
<Footer />
</React.Fragment>
);
};
I want to see the new values, but it always render the first values that I passed when creating the component.
This is the component that I create
import React from 'react';
const DisplayData = props => {
const user = props.data;
console.log('Display', user);
switch (props.type) {
case 1: //Twitter
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
</div>
<h2>{user.username}</h2>
</div>
<div className="row lg-padding">
<div className="col-sm-4">
<h4>Tweets: {user.nTweets}</h4>
</div>
<div className="col-sm-4">
<h4>Followers: {user.followers}</h4>
</div>
<div className="col-sm-4">
<h4>Followings: {user.followings}</h4>
</div>
</div>
</React.Fragment>
);
case 2: //Instagram
return <React.Fragment />;
default:
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
<h2>Instagram_User</h2>
<h4>Posts: ND</h4>
<h4>Followers: ND</h4>
<h4>Followings: ND</h4>
</div>
</div>
</React.Fragment>
);
}
};
export default DisplayData;
How can I update the data in the component or render the component when the data is updated?
Maybe your user_data might to be a state object.
// Somecomponent ...
const [user_data, setUser_data] = useState({
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...'
})
/* Rest of stuff */
const handleSubmit = async event => {
/*...*/
const userData = await getData(user.username)
setUser_data(userData)
}
// Then display the stated-stored user_data
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>

Dynamically create dropdown menu options from array with react-bootstrap

I'm building a drupal based e-commerce site right now and got stuck. Still new to react and coding in general, but trying to learn. So I've got all my data pulled in, using redux and rest api, and I'm getting my products, variations and attributes. The product page is setting a specific product based on url, and now I need to be able to select the different attributes via a dropdown menu. Currently I have a place holder dropdown that matches the one shown in react-bootstrap documentation. However, I need to be placing options in that dropdown based off of my array holding the attributes.
I'm sure it's simple but I've been searching around and haven't found an answer yet that works. Hopefully you guys can help.
As you look through the code, keep in mind that sizes = [] is the array I'm looking to place data from as the selectable options in the dropdown.
Here's the product page:
import React, { Component} from 'react';
import '../../css/Home.css';
import MenuBar from "../sub-components/MenuBar";
import LeftMenuBar from "../sub-components/LeftMenuBar";
import "../../css/ProductPage.css"
import WomensWear from "../../media/WomensWear.jpg"
import {
Dropdown,
DropdownToggle,
DropdownMenu,
DropdownItem } from 'reactstrap';
class ProductPage extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
dropdownOpen: false
};
}
toggle() {
this.setState(prevState => ({
dropdownOpen: !prevState.dropdownOpen
}));
}
getProduct() {
let product = null;
let sizes = [];
if (this.props.products && this.props.products.items.length) {
product = this.props.products.items.find(o => o.path[0].alias === this.props.router.match.url);
if (product && this.props.variations && this.props.attributes) {
product.something = [];
for (let i = 0; i < product.variations.length; i++) {
let varid = product.variations[i].target_id;
let variation = this.props.variations.items.find(o => o.variation_id[0].value === varid);
variation.size = this.props.attributes.items.find(o => o.attribute_value_id[0].value === variation.attribute_size[0].target_id);
sizes.push({value: variation.size.attribute_value_id[0].value, name: variation.size.name[0].value});
product.something.push(variation);
console.log(sizes);
}
}
}
return product;
}
render() {
let style = {
height: this.props.height - 56,
};
let product = this.getProduct();
let body = product && product.body.length ? product.body[0].value : null;
return (
<div className="App" id="default">
<div className='MenuBar'>
<MenuBar/>
</div>
<div>
<div style={style} className="ProductPage row no-gutters">
<div className="col-xs-3 col-md-3">
<LeftMenuBar/>
</div>
<div className="outer col-xs-4 col-md-4">
<div>
<div id="ProductPlacement">
<img src={WomensWear} alt=""/>
<div id="alternate-pics">
<div id="alt-pic">
</div>
<div id="alt-pic">
</div>
<div id="alt-pic">
</div>
</div>
</div>
</div>
</div>
<div className="col-xs-5 col-md-5">
<div id="ImagePlacement">
<div className="ProductTitle">
<h1>First Product</h1>
</div>
<hr/>
<div className="ProductDescription">
<div dangerouslySetInnerHTML={{__html: body}} />
</div>
<div id="options">
<div id="color">
</div>
<div id="color2">
</div>
<div id="color3">
</div>
</div>
<div id="options">
<div>
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
<DropdownToggle caret id="size-dropdown">
Size
</DropdownToggle>
<DropdownMenu>
<DropdownItem>1</DropdownItem>
<DropdownItem>3</DropdownItem>
<DropdownItem>5</DropdownItem>
</DropdownMenu>
</Dropdown>
<div className="AddToCart">
<button className="AddToCart">Add To Cart</button>
<button className="Price">$34.99</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default ProductPage;
Neat thing about React is that you can use regular JS.
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
<DropdownToggle caret id="size-dropdown">
Size
</DropdownToggle>
<DropdownMenu>
{sizes.map(size => (
<DropdownItem>{size}</DropdownItem>
))}
</DropdownMenu>
</Dropdown>
Sidenote: select seems to be more suitable element for this but that wasn't your question.

Categories

Resources