i am working with a REST API that provides data for different countries. I have a search box and when i am typing letters under the box appeared different countries that matches with the search. Each country that appears has a button beside and when you click that button some information about this country appears. I have two different components, the first component showing the countries that matches the search and the second component showing the information from the selected country.
The code of the first component:
import {useState} from 'react'
import TheCountry from './TheCountry'
const TheSearchCountry= ({countrie}) => {
const [buttonClicked, setButtonClicked] = useState(true)
return (
buttonClicked ?
countrie.map(country => (
<p key={country.name}>
{country.name}
<button onClick={() => {setButtonClicked(false)}}>show</button>
</p>
))
: <TheCountry countries={countrie} />
)
}
export default TheSearchCountry
The second component called
<TheCountry/>
When the user clicks the show button i want to call the component
<TheCountry/>
and show in the screen the details about this particular country. But something like this did not happen, i screen all the data for all the countries that matches the search query. I did not find a correct way to call my component and isolate the country that trigger the button. Can anyone help ?
Related
Please i need help trying to get the value/state of each selected checkbox in my react native project.
What I'm trying to do actually is to click on a button that navigates to "SelectProducts" screen. then the screen shows a list of items to select using checkboxes. I put the checkbox I imported from expo in a loop like the following:
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View, Alert, Image, ScrollView, TouchableOpacity } from 'react-native';
import {useNavigation} from '#react-navigation/native';
import Checkbox from 'expo-checkbox';
const SelectProducts = ({route}) => {
const navigation = useNavigation();
const [checkedBox, setCheckedBox] = useState([]);
const [itemList, setItemList] = useState([]);
{itemList.map((item, index) => (
<View key={item.id} style={styles.checkboxContainer}>
<Checkbox
value={checkedBox[index]}
onValueChange={() => {
let checkedBox = [];
checkedBox[index] = !checkedBox[index];
setCheckedBox(checkedBox);
// console.log(setCheckedBox(checkedBox));
}}
color={checkedBox ? '#800080' : undefined}
style={styles.checkbox}
/>
</View>
))}
}
export default SelectProducts;
The code above is just a part of the entire code in the "SelectProducts" screen where I'm having issues. Please let me know what I'm not during right here.
So, after selecting the checkboxes for the items I want to include when recording a sales order, the system should get the price, item name, and picture to send back to the previous screen in order to calculate the total sum, etc. when done with the item selection.
But the result I'm getting is very weird. There is now a list of items with checkboxes as expected, but once I select one of the checkboxes, then try to select another one, the previous checkbox will be unselected automatically for the current one to be selected. The checkbox selection is behaving exactly like normal radio buttons that only accept one input at a time. Meaning that my checkbox implementation isn't allowing multiple selections. This is the main challenge I'm facing at the moment.
I have even tried to print out the output of the value when selected but it's showing 'undefined'. I'm so confused here. I know this is simple to some of the developers here but I'm quite finding it hard to implement. It has already taken me some days now. Please help. Thanks!
PS: I'm currently using this guy's solution How to handle checkbox in loop react native . He used a class component implementation while I used a function component. But it's not working for me. Don't know why. Please kindly help me look into it.
This might help
itemList.map((item, index) => (
.....
<Checkbox
...
onValueChange={() => {
const newCheckedBox = [...checkedBox];
newCheckedBox[index] = !newCheckedBox[index];
setCheckedBox(newCheckedBox);
}}
...
/>
....
))
I have built a react application which shows items from JSON file, it consists of 4 main components, Items.js which created the item itself alongside its props (title and image), Itemlist.js which shows items from items.js and other functions.
MenuCat maps and shows each category from the json, and whenever the category is clicked it returns a number(props) to Itemlist.js adding it to the mapping function of items as ( children[{props here}].children[]....) so that it maps all items of each clicked category by using its json index.
Whenever an item is clicked, it shows more JSON properties such as promos inside a pop up called drawer, the content of this pop up is from Modifiers.js.
I need a function similar to MenuCat.js's category clicks but with items instead, where it shows the exact children of the item (e.g Burger 1 shows desert promo 1 on click, and burger 2 shows desert promo 2). The way its set up now, it only shows desert promo 1 for all the items.
Sandbox (current view on app.js): https://codesandbox.io/embed/8j5mmrjk2?fontsize=14&moduleview=1
One problem I noticed with your components was that you were passing the key attribute. This is anti-pattern as React does not pass down ref or key props.
If you need to access the same value within the child component, you should pass it as a different prop (ex: <ListItemWrapper key={result.id} id={result.id} />).
Just pass it down as a different attribute such as myKey.
I've done some other tweaks which you can check in the forked sandbox. Most notably, I added a state value to track the child index that was clicked.
this.state = {
itemSelected: 0
}
...
{items.children[selected].children[itemSelected].children.map(
(item, index) => (
<Modifiers
key={index}
title={item.name}
myKey={index}
childp={item.children[index].name}
>
{" "}
</Modifiers>
)
)}
Codesandbox link.
Okay, so the high level functionality of what I want this app to do:
Upon load, you're presented with the characters on the left, and on the right an intro screen.
When a user clicks on the first character (Cloud) for example, then the intro screen is replaced with Cloud's stats. If a user clicks on the second, third, etc character, same thing. The intro screen on the right is replaced with that character's specific stats.
That's basically it. I'm finding it really tough to do, for some reason.
For the /components/ folder breakdown (I'll go over the important ones):
/components/content/ - this is where the characters information lives, housed in the State. Each character is uniquely identified by an 'id'.
/components/sidebar/ - this is the sidebar component
/components/card-overview/ - this is a single component, repeated a few times, that houses the 'overview' of each character (image, character name), that you see in the sidebar itself
/components/card-detailed/ - this is where it grabs the array of objects from /components/content/, filters through and maps the character you're currently seeing to the DOM. Problem is, on line 13 of this component, you'll see I've hard-coded in the id #. Obviously, I want this to change to whatever character the user clicks, it then loads THAT character's info to the DOM. I just don't know how to do that.
In short, what I'm trying to do:
When a character on the left is clicked, hide whatever is on the right and replace it with that character's information.
I made your intention working here: https://codesandbox.io/s/l2lqm76z0q
As Chris pointed out, the way to go is using react state.
Therefore, I introduced a state with the default selected item 4 and created a handleClick function that should fire once you click on one item in your sidebar. Both of them got created in App.js:
state = {
selected: 4
};
handleClick = id => {
this.setState({ selected: id });
};
Now, I transferred the handleClick function where it is needed, in this case in Sidebar.js:
<Sidebar onClick={this.handleClick} />
And the currently selected item needs to be transferred to your content (again, where it is needed).
<Content selected={this.state.selected} />
In the sidebar, I send the handleClick function again to the it's child, CardOverview, with the related id(*):
<CardOverview
image={cloudImage}
name="Cloud Strife"
onClick={() => this.props.onClick(1)}
/>
And in CardOverview, finally, we use that function we passed down the road:
<section className="card-overview" onClick={this.props.onClick}>
...
</section>
(Whether it is working or not, we see in the console - when clicking on on item, it should show the state with the currently selected item id.)
Now, in content.js, we use the selected value and pass it down to CardDetailed where we use it in the following way:
// Grab the 'characters' object from App.js, and assign it to 'this.props'
const { characters, selected } = this.props;
// Filter the chracters and return only whose 'id' belongs to that of the selected one
const filteredCharacters = characters
.filter(character => character.id === selected)
.map(character => (
<div className="characters" key={character.id}>
<p>Name: {character.Name}</p>
<p>Job: {character.Job}</p>
<p>Age: {character.Age}</p>
<p>Weapon: {character.Weapon}</p>
<p>Height: {character.Height}</p>
<p>Birthdate: {character.Birthdate}</p>
<p>Birthplace: {character.Birthplace}</p>
<p>Bloodtype: {character.Bloodtype}</p>
<p>Description: {character.Description}</p>
</div>
));
...
That`s it.
(*) Be aware, I did not improve your code, I just made it working. I see several issues that you should tackle. E.g. it is not needed to list all the characters in your sidebar manually. I'd suggest to create a file that contains your list of characters and use it in sidebar and in content. This way, you will reduce your code and maintain your characters list (and all belonging information like id) in one file.
Please take a look at my code for Dropdown,
I'm using the semantic ui react dropdown on an EditProfile component. I have pasted a sample code here, https://codesandbox.io/s/m4288nx4z8, but I could not get it to work because I'm not very familiar with functional components in React, I've always used Class component. But you can check the full code for the whole component below in the github gist.
https://gist.github.com/mayordwells/b0cbb7b63af85269091f1f98296fd9bb
Please, I need help on inserting values from multiple select options of a Dropdown into the Database and also a way to display that back upon viewing the profile edit page again.
I'm using semantic-ui-react in react + rails app.
Also when I insert a value using a normal drop down without multiple select, the value gets persisted into the database.
<Dropdown
placeholder='Select Country'
fluid
search
selection
options={countryOptions}
name='country'
defaultValue={this.state.extraInfo.country}
onChange={(e) => this.handleExtraInfoChange('country', e)}
/>
This code handles change for the dropdown elements.
handleExtraInfoChange = (name, event) => {
let value;
if (event.target.value !== undefined) {
value = event.target.value;
} else {
value = event.target.textContent;
}
let newExtraInfo = Object.assign(this.state.extraInfo, { [name]: value })
this.setState({ extraInfo: newExtraInfo});
}
But when I visit the page again, I get a white blank in the input box. Here's a screen pic for that. When I comment out the defaultValue or value property(i have tried with defaultValue and value), the white blank disappears, but the value picked by a user is also not seen.
Please advice what is a possible solution to this misbehavior? And what is the best way to insert multiple values into the Database?
Thanks in advance for your time.
A functional component does not have state, it's used for composition; you want to store state, so you either have to create a Component class or you need an external state container like redux.
I have a react project, a recipe box, which includes the ability to open a recipe and add/delete ingredients. Here is a fiddle. You can click the recipe name to open the recipe. There is an edit button which reveals the delete button and gives the option to change the name of the ingredients. When the 'delete ingredient' button is pressed, the last ingredient appears to always be deleted, regardless of which ingredient is selected, but when the 'done' button is clicked and the editable input boxes change back to text, the correct change is shown, the proper ingredient deleted and the last ingredient remains. Though this works functionally, it's obviously not very UI friendly, and I wondered why this was happening. Any help would be great.
jsFiddle
class Input extends React.Component {
render() {
const array = this.props.update;
let booleanButton = null;
if (this.props.ingr) {
////////////////////////////
// here is the button's JSX
booleanButton = <button onClick=
{this.props.handleDeleteIngredient.bind(this, array)}>delete
ingredient</button>;
///////////////////////////
}
return (<div><form><input type="text" defaultValue={this.props.text}
onChange={this.props.onChange.bind(this, array)} /></form>{booleanButton}
</div>)
}
}
And the handler:
handleDeleteIngredient(data, e ) {
var key = data[2];
var ingrs = this.state.ingrs;
ingrs.splice(key, 1);
this.setState({ingrs:ingrs});
}
Your description is quiet confusing, and according the your fiddle code I think your problem is caused by not setting a good key for your list Item.
from what it looks in this line, you don't have a key={ingrs[i]} props, try set it to id see it will work, but making ingrediant name as key is probably not a good idea, try to give an actual id.
ingrList.push(<Input key={ingrs[i]} handleDeleteIngredient={this.handleDeleteIngredient.bind(this)} id={id} update={[this.props.objectIndex, "ingrs", i]} onChange={this.onInputChangeIng.bind(this)} text={ingrs[i]} />);