How do I render a message when there are no filtered results in React? - create-react-app

I have a search bar that updates the state based on user input. Components that don't match the keywords I've set up will get filtered out and will not render to the screen. How do I display a message when there are no matches in the search bar?
An example can be found on CodeSandbox here:
https://codesandbox.io/embed/search-bar-test-odxw8
I am using an array of objects to store the data. I'm using the map function to separate the data into individual components, and the filter function to perform a re-render as the user inputs a word.
I tried using logic that says "if the array length is 0, display the message". The problem with that is the array is apparently always the same length and isn't connected to the amount of items being rendered to the screen.
I also tried using logic that says "if the inputted word doesn't match the object's keywords, display the message". This doesn't throw an error, but it also does not work as expected. The message remains visible at all times.
My state:
this.state = {
AnimalList,
AnimalFilter: ""
};
An example of my conditional logic:
{/* This is where I'm trying to place the conditional logic */}
{/* For example, typing "pig" should make this appear */}
{this.state.AnimalFilter!== AnimalList.keywords && (
<h2>No Results</h2>
)}
The filter and map methods:
<div className="container">
{AnimalList.filter(animal =>
animal.keywords
.toLocaleLowerCase()
.includes(this.state.AnimalFilter.toLocaleLowerCase())
).map(({ object1, object2, object3 }, index) => (
<AnimalCard
key={index}
object1={object1}
object2={object2}
object3={object3}
/>
))}
</div>
The Data:
export default [
{
object1: "horse",
object2: "goat",
object3: "panda",
keywords: "horse goat panda"
},
{
object1: "horse",
object2: "cat",
object3: "cow",
keywords: "horse cat cow"
},
{
...
},
...
];
I expect for the message to display to the screen when a user inputs a word that "doesn't exist". As of now, the message will either display the entire time or not at all.

Related

Trying to block user from typing numbers on an antd Input without having to use state (or useState)

I'm using antd Form and have some Inputs in it. I wish to know if antd has something that can validate the users input and determine if what he typed are letters or numbers. I want the input to only allow the user to type (show) in the input only alphabets but not numbers.
Form.Item has a property called rules where you can establish a pattern using RegExp, but this is not what I want, because the user can still type numbers and they will be shown on the UI. Pattern property only pops a message like "field does not accept numbers" and I assume that when I submit the data it will take what the user typed regardless of the failed rule/pattern.
I have been able to do what I'm asking by having to create a state with an object with all my values, removing the name property from the Form.Item and adding it to the Input, along with an onChange and value property but this requires more "wiring'. If you have worked with antd Form, there is an onFinish property that collects all the data so you don't have to create a separate state.When removing the name property from Form.Item, antd won't be able to collect the data of the form anymore thus rendering it useless. I wish to know if antd has something that can help me achieve what I typed in the beginning.
Following code does what I want, but uses state.
My Form.Item
<Form.Item
// name="nombre"
label="Nombre(s)"
rules={[
{ required: false, message: "REQUIRED_ERROR_MESSAGE" },
{
pattern: new RegExp(/^[a-záéíóúüñçA-Z]*$/i),
message: "field does not accept numbers",
},
]}
>
<Input
onChange={handleWordInput}
value={altaFormValues.nombre}
name="nombre"
/>
</Form.Item>
My Input handler function:
const handleWordInput = (e) => {
console.log("e", e.target.value);
const re = /^[a-záéíóúüñçA-Z\s]*$/;
const { name, value } = e.target;
if (value === "" || re.test(value)) {
setAltaFormValues((prevState) => {
return { ...prevState, [name]: value };
});
}
};

Vue Google Place Autocomplete-how can I make the selected value display?

I am implementing the component like this:
<place-autocomplete-field
v-model="field"
name="field"
label="Address lookup"
:api-key="api_key.api_key"
placeholder="Start typing here"
#autocomplete-select="onPlaceInput"
>
</place-autocomplete-field>
...
data() {
return {
api_key,
field: null
};
...
While the #autocomplete-select event fires fine, and delivers the selected value, the value displayed in the component's input field does not update on selecting from the place options. All that is in the input field is whatever was typed in there. This is not how it works in the demo on Github. Can anyone spot what I may be doing wrong?

Add search to react-native firebase list

I have a react-native list populated from firebase. I want to add a search bar on top of the app. Once I start typing, I want that list to only show results related to the search term. Its similar to this: https://www.freecodecamp.org/news/how-to-build-a-react-native-flatlist-with-realtime-searching-ability-81ad100f6699/
Only problem is the way my data is typed after its retrieved from firebase, its impossible to use the tutorial above to retrieve that data.
My html code is:
<Toolbar title="Hello World"/>
<Button
title="Add New"
type = "outline"
onPress={this.addItem.bind(this)}
/>
<ListView
dataSource={this.state.itemDataSource}
renderRow={this.renderRow}
/>
My Firebase retrieval code is as follows:
getItems(itemsRef) {
itemsRef.on('value', (snap) => {
let items = [];
snap.forEach((child) => {
items.push({
title: child.val().DESCRIPTION,
text: child.val().BASE,
_key: child.key
});
});
this.setState({
itemDataSource: this.state.itemDataSource.cloneWithRows(items)
});
});
}
I just don't know how to add a search bar that searches the retrieved list and displays only relevant stuff on the list as someone types a word in.
Pease help. I'm guessing the type of the data is what is causing the problem.
Results should look like this App. I built this on AppSheet:
https://www.appsheet.com/start/ab7f8d5d-1adf-4107-bdd8-f7022a1a81f8

how to map a value from an object array into the style of a render element

i have an object array like this. [{message:"text 1", likecolor:"blue"},{message:"text 2", likecolor:"yellow"}]. i am able to iterate the value of "message" into my Text element. However i cant assign the value of likecolor to the color of my icon. In my code below it doesnt make any changes to the color of the icon. Here is my code
/**
this is my object array
[{message:"text 1", likecolor:"blue"},{message:"text 2",likecolor:"yellow"}]
*/
this.state.messagestable.map((count) => {
return (
<Card transparent key={count.message_id}>
<Text>{count.message}</Text>
<Icon name ="ios-heart" style={{color:count.likecolor}} />
</Card>
)
}
I think you can add your color just by doing
<Icon color={count.likecolor}/>
UPDATE.
i created a snack that works, the code is like yours, see if you find some differences: https://snack.expo.io/SJ1EQQ8bH

Rendering sections in flatlist/sectionlist from one data set

I have some JSON data that looks like this:
{
"distance":"1",
"name":"whatever",
"listPriority":"1",
}
I'm passing this into a Flatlist:
<FlatList
key={'my-list'}
data={JSON}
renderItem={this.renderCard}
keyExtractor={(item, index) => index.toString()}
/>
What I want to do is section off the data based on list priority, so all items with a value for listPriority key of 1 would show under my section header that says "These are items for 1", and a value of listPriority key of 2 would have a section header that says "Section header 2", and so forth.
I.e. resulting in something like this:
List Priority 1
item in the list
item in the list
List Priority 2
item in the list
item in the list
List Priority 3
item in the list
item in the list
How can I get sections into my Flatlist?
Sectionlist seems to be only if you are passing in separate data sets for each manually entered section.
It would seem that you could use the SectionList component, that would give you the headers and (if you want) them being sticky, which is a nice to have behaviour.
So you just need to create an array of objects that follow the needed format for the component to work properly.
<SectionList
renderItem={({item}) => someFunctionHere(item)/<SomeComponent item={item}>}
sections={sections}
keyExtractor={(item, index) => index.toString()}
/>
Define sections to be an array of format:
[
{
title: "List priority 1",
data: [{"distance":"1", "listPriority": "1"...}, ...]
},
{
title: "List priority 2",
data: [{"distance":"20", "listPriority": "2"...}, ...]
},
...
]
So again, just format your data (most probably within the componentDidMount hook) and when then data is formatted you can include it into the state and eventually feeding it into the SectionList component so that it will re-render