Iam doing one of the react assignment and I am stuck on the last part of this assignment. The question is like this: Improve on the application in the previous exercise, such that when the names of multiple countries are shown on the page there is a button next to the name of the country, which when pressed shows the view for that country. Here is my code. I tried some functions but couldnot get it so I wonder if someone can help me to cope with this last part..Thank you
import React, { useState, useEffect } from "react";
import axios from "axios";
import ReactDOM from "react-dom";
const App = () => {
const [countries, setCountries] = useState([]);
const [filter, setFilter] = useState("");
const [select, setSelected] = useState([]);
//console.log(countries);
useEffect(() => {
axios.get("https://restcountries.eu/rest/v2/all").then((response) => {
setCountries(response.data);
});
}, []);
const searchHandler = (e) => {
setFilter(e.target.value);
//console.log(filter);
const selected_countries = countries.filter((item) => {
const letter_case=item.name.toLowerCase().includes(filter.toLowerCase())
return letter_case
});
setSelected(selected_countries);
};
const countryLanguages = (languages)=>
languages.map(language => <li key={language.name}>{language.name}</li>)
const showCountries = () => {
if (select.length === 0) {
return <div></div>
} else if (select.length > 10) {
return "Find the specific filter";
}
else if(select.length>1 && select.length<10){
return (select.map(country=>
<div key={country.alpha3code}>{country.name}
<button>Show</button>//this part
</div>)
)
}
else if(select.length===1){
return(
<div>
<h1>{select[0].name}</h1>
<div>capital {select[0].capital}</div>
<div>population {select[0].population}</div>
<h2>languages</h2>
<ul>{countryLanguages(select[0].languages)}</ul>
<img src={select[0].flag} width="100px"/>
<h2>Weather in {select[0].capital}</h2>
</div>
)
}
};
return (
<div>
<h1>Countries</h1>
find countries: <input value={filter} onChange={searchHandler} />
{showCountries()}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
Create a separate component.
const SingleCountry = ({name}) => {
const [ showDetails, setShowDetails ] = useState(false);
const toggleDetails = () => setShowDetails(!showDetails); //toggles the variable true/false
return ( <div>
<button onClick={toggleDetails}>Show Details</button>
{ /* renders the <div> only if showDetails is true */ }
{ showDetails && <div>These are the details of the country {name}</div> }
</div>)
}
Edit your showCountries component to use the new component.
const showCountries = () => {
if (select.length === 0) {
return <div></div>
} else if (select.length > 10) {
return "Find the specific filter";
}
else if(select.length>1 && select.length<10){
return (select.map(country=> <SingleCountry key={country.alpha3code} name={country.name} />
)
}
Related
I have 2 buttons, Single Component and Multiple Component.
When I click on Multiple Component, I expect it to add 3 components, but it adds only 1.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { observer } from "mobx-react-lite";
function App() {
const [component, setComponent] = useState([]);
useEffect(() => {});
const newArray = [1, 2, 3];
const Test = observer(() => {
return (
<div>
<p>Test</p>
</div>
);
});
const Test2 = observer(() => {
return (
<div>
<p>Test2</p>
</div>
);
});
const Test3 = observer(() => {
return (
<div>
<p>Test3</p>
</div>
);
});
async function MultipleComponent() {
newArray.map(async (x) => {
if (x === 1) {
await setComponent([...component, Test]);
} else if (x === 2) {
await setComponent([...component, Test2]);
} else {
await setComponent([...component, Test3]);
}
console.log(x);
});
}
return (
<div>
{component.map((Input, index) => (
<Input components={component} key={index} />
))}
<button onClick={() => setComponent([...component, Test])}>
Single Component
</button>
<button onClick={() => MultipleComponent()}>Multiple Component</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
codensadbox: https://codesandbox.io/s/react-hooks-useeffect-forked-edmgb5
There is no point in using await on setState, nowhere the docs say it is a good idea.
On the other hand you need to use version of setState which accepts an updater function, there you can get previous state.
setComponent(ps=>[...ps, Test2])
Also, I don't have link to official docs, but I am not sure storing components inside state is good idea either. You could store some identifier in state which indicates which component it is and then render that one when time comes. Here is what I mean by this:
let Test1 = (props) => {
return <div>1</div>;
};
let Test2 = (props) => {
return <div>2</div>;
};
let GeneralComponent = (props) => {
if (props.comp === '1') return <Test1 />;
if (props.comp === '2') return <Test2 />;
return null;
};
export default function App() {
let [comp, setComp] = React.useState('1');
return (
<div onClick={() => setComp(comp === '1' ? '2' : '1')}>
<GeneralComponent comp={comp} />
</div>
);
}
The GeneralComp accepts an identifier of which component to render, which is stored in state in parent.
I am trying to optimize my react application, while profiling my application I found that when I click on Add to cart page my whole page is getting re-rendered. Could anyone help me with, how to avoid that and why it is happening?
FYR, GitHub repo:https://github.com/sandeep8080/shopping-cart-assignment
import { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import SideBar from "../../components/sideBar/SideBar";
import { getProductsData } from "../../redux/action/products";
import ProductCard from '../../components/productCard/ProductCard';
import './products.css';
import { getCategoryData } from "../../redux/action/category";
import Cart from "../cart/cart";
import Modal from '../../components/modal/Modal';
import { useHistory, useParams } from "react-router";
const ProductsPage = () => {
const dispatch = useDispatch();
const router = useHistory();
const { id } = useParams();
console.log(` product comp : ${id}`);
const productsData = useSelector(data => data.Products.products);
const sideBarData = useSelector(data => {
const listItems = data.Categories.CategoriesItems;
const activeListItems = listItems.filter(item => item.enabled === true);
return activeListItems;
});
const openCart = useSelector(state => state.CartDetails.isOpen);
const [fProductData, setFProductData] = useState([]);
useEffect(() => {
dispatch(getProductsData());
dispatch(getCategoryData());
}, []);
useEffect(() => {
if (id) {
filterDataByCategory(id);
} else {
setFProductData(productsData);
}
}, [productsData, id]);
// Function to filter out the data based on category
const filterDataByCategory = (id) => {
console.log("Filter data function called")
const filterData = productsData.filter(item => item.category === id);
setFProductData(filterData);
};
const handleClickProduct = useCallback((id) => {
filterDataByCategory(id);
router.push(`/products/${id}`);
}, [id]);
return (
<div className='product-main'>
<SideBar
sideBarData={sideBarData}
handleClickProduct={handleClickProduct}
/>
<div className='product-container'>
<div className='product-row'>
{
(fProductData).map((product) => {
return (
<div key={product.id} className='card-wrapper' >
<ProductCard key={product.id} {...product} />
</div>
)
})
}
</div>
</div>
{
openCart &&
<Modal>
<Cart />
</Modal>
}
</div >
)
};
export default ProductsPage;
// Product Card component
import './ProductCard.css';
import Button from '../button/Button';
import React from 'react';
import { useDispatch } from 'react-redux';
import { updateCart } from '../../redux/action/cart';
import priceFromatter from '../../lib/priceFromatter';
const ProductCard = ({ name, price, description, imageURL, id }) => {
const dispatch = useDispatch();
const handleClick = () => {
console.log('product clicked', id);
dispatch(updateCart(id, 'add'));
};
let imgURL = `../../${imageURL}`;
// imgURL = imgURL.replace(/([^:]\/)\/+/g, "$1");
// const image = React.lazy(() => import (`${imgURL}`));
// console.log(image);
return (
<article className='card-container'>
<h6 className='card-header'>
{name}
</h6>
<div className='content-container'>
<img
className='content-img'
// src={require(`${imgURL}`).default}
src={imageURL}
/>
<div className='content'>
<p className='content-desc'>{description}</p>
<div className='content-footer'>
<p>{priceFromatter(price)}</p>
<Button btnText='Add To Cart' handleClick={() => handleClick(id)} />
</div>
</div>
</div>
</article>
)
};
export default ProductCard;
import { callApi } from "../../lib/api";
import { actions } from '../actionContants/actionConstant';
export const toggleCart = (isToggle) => {
return {
type: actions.OPEN_CART,
payload: isToggle,
}
};
export const updateCart = (id, operation) => {
return async (dispatch, getState) => {
const productList = getState().Products.products;
const cartItems = getState().CartDetails.cartItems;
const currItem = productList.find(({ id: currentItemId }) => currentItemId === id);
const isItemInCart = cartItems.find(({ id }) => id === currItem.id);
let finalItem = [];
if (!isItemInCart) {
finalItem = [...cartItems, { ...currItem, count: 1 }]
} else {
finalItem = cartItems.map(item => {
if (item.id === currItem.id) {
operation === 'add' ? item.count = item.count + 1 : item.count = item.count - 1
}
return item;
}).filter(({ count }) => count)
}
try {
const result = await callApi.post('/addToCart', id);
result && dispatch({
type: actions.UPDATE_TO_CART,
payload: finalItem
})
} catch (error) {
console.log(error)
}
}
};
In products.js change the following block of code:
const sideBarData = useSelector(data => {
const listItems = data.Categories.CategoriesItems;
const activeListItems = listItems.filter(item => item.enabled === true);
return activeListItems;
});
to:
const sideBarData = useSelector(data => {
const listItems = data.Categories.CategoriesItems;
const activeListItems = listItems.filter(item => item.enabled === true);
return activeListItems;
}, shallowEqual);
useSelector will force a component to re-render when the selector returns a new reference that is different than the previous reference (it uses the === operator). Ref: https://react-redux.js.org/api/hooks#equality-comparisons-and-updates. As you are filtering the array returned from the store, it will always be a different object reference to the one in the store.
The use of shallowEqual as the equalityFn to useSelector() can be used to change the comparison and prevent an unnecessary re-render of the <ProductsPage> component.
did you try using e.preventDefault() otherwise the answer above might work
So I was trying to update the value I got by the Addlist and I tried this but this isn;t working. Also when I click on the '+' button without writing anything, an empty list is created. How should I stop it. I've attached a code below.
import React from "react";
import "./App.css";
import { useState } from "react";
import TodoList from "./components/TodoList";
function App() {
const [input, setInput] = useState("");
const [list, setList] = useState([]);
const updateList = (e) => {
setInput(e.target.value);
};
const AddList = () => {
console.log("value added")
setList((addValue) => {
return [...addValue, input];
});
setInput("");
};
const updateItems=(id)=>{
const newValue=[...list].map((newVal)=>{
if(input.id===id){
input.text='';
}
return newVal;
})
setList(newValue);
}
const deleteItems = (id) => {
console.log("deleted");
setList((addValue) => {
return addValue.filter((element, index) => {
return index !== id;
});
});
};
return (
<div className="todo-app">
<h1> Enter Anything</h1>
<input
type="text"
placeholder="Add anything"
value={input}
onChange={updateList}
/>
<button onClick={AddList}>+</button>
<ul>
{list.map((itemsvalue, id) => {
return (
<TodoList
itemsValue={itemsvalue}
key={id}
onSelect={deleteItems}
id={id}
onUpdate={updateItems}
/>
);
})}
</ul>
</div>
);
}
export default App;
Any kind of help would be appreciated. Also if I want to split this into multiple components is there a way to do.
When user clicks on the add button there is the check for empty String AddList method
for ex:- User updates second index value, second position value will get updated.
const [input, setInput] = useState('');
const [list, setList] = useState([]);
const [index, setIndex] = useState(null);
const updateList = (e) => {
setInput(e.target.value);
};
useEffect(() => {
setList(list);
console.log(list, '<>?');
}, [index]);
const AddList = () => {
if (input.trim() !== '') {
setList([...list, input]);
}
setInput('');
};
const updateValue = (index) => {
console.log(list[index]);
setIndex(index);
if (list[index].trim() !== '') {
setInput(list[index]);
}
};
const UpdateList = () => {
list[index] = input;
console.log(list, 'before <>?');
setIndex(null);
setInput('');
};
return (
<div>
<input type="text" placeholder="Add anything" value={input} onChange={updateList} />
<button disabled={!index && !list.length === 0} onClick={AddList}>
Add
</button>
<button disabled={input.trim() === ''} onClick={UpdateList}>
Update
</button>
{list.map((m, index) => (
<h1 style={{ border: '1px solid black' }} onClick={() => updateValue(index)}>
{m}
</h1>
))}
</div>
);
I'm using React trying to make a full crud application, but I can't figure out how to make the name and area for the rooms created in the houses change. Does anyone have any suggestions or know how to make this work?
Also sorry for all the code idk what is needed for people to see.
App.js
import React, { Component } from 'react';
import { HousesList } from './Components/Houses-List'
// import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div>
<HousesList/>
</div>
)
}
}
export default App;
House.js
import React from 'react';
import { NewRoomForm } from './NewRoomForm';
import { EditRoomForm } from './EditRoomForm';
export const House = (props) => {
const { house, updateHouse } = props;
const deleteRoom = (roomId) => {
const updatedHouse = {
...house,
rooms: house.rooms.filter((x) => x._id !== roomId)
};
updateHouse(updatedHouse);
}
const addNewRoom = (room) => updateHouse({ ...house, rooms: [...house.rooms, room]});
const rooms = () => (
<ul>
{house.rooms.map((room, index) => (
<li key={index}>
<label> {`${room.name} Area: ${room.area}`} </label>
<button onClick={(e) => deleteRoom(room._id)}>Delete Room</button>
<EditRoomForm />
<h1> </h1>
</li>
))}
</ul>
);
return (
<div>
<h1>{house.name}</h1>
{
rooms({ rooms, houseId: house._id, deleteRoom})
}
<NewRoomForm addNewRoom={addNewRoom} />
{/* <EditRoomForm addNewRoom={addNewRoom} /> */}
</div>
)
};
EditRoomForm.js
import React, { useState } from 'react';
export const EditRoomForm = (props) => {
const [name, setName] = useState('');
const [area, setArea] = useState('');
const handleAreaInput = (e) => {
const int = parseInt(e.target.value, 10);
setArea(int >= 0 ? int : '');
}
const onSubmit = (e) => {
e.preventDefault();
if (name && area) {
console.log("name: " + name)
console.log("area: " + area)
setName('');
setArea('');
console.log("name: " + name)
console.log("area: " + area)
} else {
console.log('invalid input');
}
};
return (
<div>
<form onSubmit={onSubmit}>
<input
type='text'
placeholder='name'
onChange={(e) => setName(e.target.value)}
value={name}
/>
<input
type='text'
placeholder='area'
onChange={handleAreaInput}
value={area}
/>
<button type='submit'>Edit Room</button>
</form>
</div>
)
};
NewRoomForm.js
import React, { useState } from 'react';
export const NewRoomForm = (props) => {
const [name, setName] = useState('');
const [area, setArea] = useState('');
const handleAreaInput = (e) => {
const int = parseInt(e.target.value, 10);
setArea(int >= 0 ? int : '');
}
const onSubmit = (e) => {
e.preventDefault();
if (name && area) {
props.addNewRoom({name, area});
setName('');
setArea('');
} else {
console.log('invalid input');
}
};
return (
<div>
<h4>Add a new room</h4>
<form onSubmit={onSubmit}>
<input
type='text'
placeholder='name'
onChange={(e) => setName(e.target.value)}
value={name}
/>
<input
type='text'
placeholder='area'
onChange={handleAreaInput}
value={area}
/>
<button type='submit'>Add/Edit Room</button>
</form>
</div>
)
};
Houses-List.js
import React from 'react';
import { House } from './House';
import { housesApi } from '../rest/HousesApi';
import { NewRoomForm } from './NewRoomForm';
// import { EditRoomForm } from './edit';
export class HousesList extends React.Component {
state = {
houses: []
};
componentDidMount() {
console.log("Inside componentDidMount Funcaton Block")
this.fetchHouses();
}
fetchHouses = async () => {
console.log("Inside fetchHouses Funcaton Block")
const houses = await housesApi.get();
this.setState({ houses });
}
updateHouse = async (updatedHouse) => {
console.log("Inside updateHouse Funcaton Block")
console.log("housesApi Check: " + housesApi)
await housesApi.put(updatedHouse);
this.fetchHouses();
};
render() {
console.log("Inside render of Houses-List")
console.log(this.state.houses);
return (
<div className="house-list">
{this.state.houses.map((house) => (
<House
house={house}
key={house._id}
updateHouse={this.updateHouse}
/>
))}
<NewRoomForm />
</div>
)
}
}
HousesApi.js
const HOUSES_ENDPOINT = "https://ancient-taiga-31359.herokuapp.com/api/houses";
class HousesApi {
get = async () => {
try {
console.log("Inside Try Block Of HousesAPI get funcation")
const resp = await fetch(HOUSES_ENDPOINT);
const data = await resp.json();
return data;
} catch(e) {
console.log("Oops, looks like fetchHouses has an issue", e)
}
}
put = async (house) => {
try {
console.log("Inside Try Block Of put funcation")
console.log(house)
console.log("HOUSES_ENDPOINT: " + HOUSES_ENDPOINT + house._id)
console.log("house._id: " + house._id)
const resp = await fetch(`${HOUSES_ENDPOINT}/${house._id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(house)
});
console.log("The body is: " + JSON.stringify(house))
// console.log(" resp.json(): " + resp.json())
console.log("At The End OF Try Block Of put funcation")
return await resp.json();
} catch(e) {
console.log("Oops, looks like updating houses has an issue", e)
}
}
}
export const housesApi = new HousesApi();
Before helping on the code, I will explain the concept on updating the rooms based on your code structure.
The EditRoomForm needs to rendered with selected room props and curried function with index parameter.
The EditRoomForm has its own state of room which will be updated when there is an incoming selected room props by using useEffect.
User updates the name and area and click submit which will trigger a callback function props which will send back the new name and area and update those new name and area by using index inside the house.rooms.
Parent House.js will call the house API PUT method with updated details.
With the steps above, you will need to update your code like this.
House.js
import React from 'react';
import { NewRoomForm } from './NewRoomForm';
import { EditRoomForm } from './EditRoomForm';
export const House = (props) => {
const { house, updateHouse } = props;
const deleteRoom = (roomId) => {
const updatedHouse = {
...house,
rooms: house.rooms.filter((x) => x._id !== roomId)
};
updateHouse(updatedHouse);
}
const updateRoom = (index) => (name,area) => {
const updatingHouse = JSON.parse(JSON.stringify(house));
updatingHouse.rooms[index] = {...updatingHouse.rooms[index], name,area}
updateHouse(updatingHouse );
}
const addNewRoom = (room) => updateHouse({ ...house, rooms: [...house.rooms, room]});
const rooms = () => (
<ul>
{house.rooms.map((room, index) => (
<li key={index}>
<label> {`${room.name} Area: ${room.area}`} </label>
<button onClick={(e) => deleteRoom(room._id)}>Delete Room</button>
<EditRoomForm selectedRoom={room} onSubmit={updateRoom(index)} />
<h1> </h1>
</li>
))}
</ul>
);
return (
<div>
<h1>{house.name}</h1>
{
rooms({ rooms, houseId: house._id, deleteRoom})
}
<NewRoomForm addNewRoom={addNewRoom} />
</div>
)
};
EditRoomForm.js
import React, { useState,useEffect } from 'react';
export const EditRoomForm = (props) => {
const [name, setName] = useState('');
const [area, setArea] = useState('');
const {selectedRoom} = props;
useEffect(() => {
setName(selectedRoom.name);
setArea(selectedRoom.area);
}, [selectedRoom] )
const handleAreaInput = (e) => {
const int = parseInt(e.target.value, 10);
setArea(int >= 0 ? int : '');
}
const onSubmit = (e) => {
e.preventDefault();
if (name && area) {
console.log("name: " + name)
console.log("area: " + area)
props.onSubmit(name,area);
setName('');
setArea('');
console.log("name: " + name)
console.log("area: " + area)
} else {
console.log('invalid input');
}
};
return (
<div>
<form onSubmit={onSubmit}>
<input
type='text'
placeholder='name'
onChange={(e) => setName(e.target.value)}
value={name}
/>
<input
type='text'
placeholder='area'
onChange={handleAreaInput}
value={area}
/>
<button type='submit'>Edit Room</button>
</form>
</div>
)
};
You get the idea.
You can add a button and use useState hook to keep the state. On button click set the editingRoom state to true. On state change the component will be re-rendered and EditForm component will be shown. You need to pass proper props. And once editing is completed please reset the editingRoom state to false.
import React, { useState } from 'react';
const [editingRoom, setEditingRoom] = useState(false);
const handleEditRoom = (room) => {
.......
setEditingRoom(false);
}
const rooms = () => (
<ul>
{house.rooms.map((room, index) => (
<li key={index}>
<label> {`${room.name} Area: ${room.area}`} </label>
<button onClick={(e) => deleteRoom(room._id)}>Delete Room</button>
{!editingRoom && <button onClick={(e) => seEditingRoom(true)}>Edit Room</button>}
{editingRoom && <EditRoomForm handleEditRoom={handleEditRoom} />}
<h1> </h1>
</li>
))}
</ul>
I'm using global giving API to make a charity finder app.
I have two dropdowns and a search button in the CharityFinderPage.js component. Now on clicking the search button, I want to fetch the charities using the themeId. The endpoint is https://api.globalgiving.org/api/public/projectservice/themes/{themeId}/projects
I know that on handleClick I should fetch the charities, but how do I get the value of themeId in the handleClick of CharityFinderPage.js component.
What I want is to show a new card component when the button clicks like showing a charity card with the fields populated on it from the data of the API, but first I need to be able to get the data from the API, then I can render a new component.
Here's the code:
CharityFinderPage.js
const CharityFinderPage = () => {
const handleClick = () => {
console.log("inside handleclick")
}
return (
<div style={containerStyle}>
<h1>Charity Finder ❤️</h1>
<h3>Search for charity</h3>
<h4>
Filter charities by personal search conditions. Use the dropdown below
to see charities matching your criteria.
</h4>
<Themes />
<Regions />
<button onClick={handleClick}>Search</button>
</div>
)
}
export default CharityFinderPage
Themes.js
import React, { useEffect, useState } from "react"
import axios from "axios"
const url = `https://api.globalgiving.org/api/public/projectservice/themes.json?api_key=${process.env.REACT_APP_api_key}`
const Themes = () => {
const [isLoading, setIsLoading] = useState(false)
const [selectValue, setSelectValue] = useState("")
const [themes, setThemes] = useState([])
useEffect(() => {
const fetchThemes = async () => {
try {
setIsLoading(true)
const result = await axios.get(url)
setThemes(result.data.themes.theme)
setIsLoading(false)
} catch (err) {
console.log(err)
}
}
fetchThemes()
}, [])
const handleChange = (event) => {
console.log("inside handleChange", event.target.value)
setSelectValue(event.target.value)
}
return (
<div>
{isLoading ? (
<h4>Loading......</h4>
) : (
<div>
<label>Select theme: </label>
<select onChange={handleChange} value={selectValue}>
{themes.map((theme, id) => {
return <option key={id}>{theme.name}</option> //{id} is the `themeId`
})}
</select>
</div>
)}
</div>
)
}
export default Themes
Regions component is exactly similar to Themes.
So the thing that you need to do here is called lifting the state up.
You need to move your states of theme component to CharityFinder component
I am lifting only selectedValue because that is all that you need
CharityFinderPage.js
const CharityFinderPage = () => {
const [selectValue, setSelectValue] = useState("")
const handleClick = () => {
console.log(`inside handleclick with ${selectValue}`)
}
return (
<div style={containerStyle}>
<h1>Charity Finder ❤️</h1>
<h3>Search for charity</h3>
<h4>
Filter charities by personal search conditions. Use the dropdown below
to see charities matching your criteria.
</h4>
// you can pass the setSelectValue as prop to Themes component
<Themes setSelectValue={setSelectValue} selectValue={selectValue} />
<Regions />
<button onClick={handleClick}>Search</button>
</div>
)
}
export default CharityFinderPage
Theme.js
import React, { useEffect, useState } from "react"
import axios from "axios"
const url = `https://api.globalgiving.org/api/public/projectservice/themes.json?api_key=${process.env.REACT_APP_api_key}`
const Themes = ({ selectValue, setSelectValue }) => {
const [isLoading, setIsLoading] = useState(false)
const [themes, setThemes] = useState([])
useEffect(() => {
const fetchThemes = async () => {
try {
setIsLoading(true)
const result = await axios.get(url)
setThemes(result.data.themes.theme)
setIsLoading(false)
} catch (err) {
console.log(err)
}
}
fetchThemes()
}, [])
const handleChange = (event) => {
console.log("inside handleChange", event.target.value)
setSelectValue(event.target.value)
}
return (
<div>
{isLoading ? (
<h4>Loading......</h4>
) : (
<div>
<label>Select theme: </label>
<select onChange={handleChange} value={selectValue}>
{themes.map((theme, id) => {
return <option key={id}>{theme.name}</option> //{id} is the `themeId`
})}
</select>
</div>
)}
</div>
)
}
export default Themes
You can do this.
const CharityFinderPage = () => {
const [themeId, setThemeId] = useState();
const handleClick = () => {
console.log("inside handleclick")
// make call to endpoint with themeId
}
return (
<div style={containerStyle}>
<h1>Charity Finder ❤️</h1>
<h3>Search for charity</h3>
<h4>
Filter charities by personal search conditions. Use the dropdown below
to see charities matching your criteria.
</h4>
<Themes setThemeId={setThemeId} />
<Regions />
<button onClick={handleClick}>Search</button>
</div>
)
}
export default CharityFinderPage
Then in Themes.js:
...
const handleChange = (event) => {
console.log("inside handleChange", event.target.value)
props.setThemeId(event.target.value);
setSelectValue(event.target.value)
}
...