Rendering sections in flatlist/sectionlist from one data set - react-native

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

Related

How to refresh the list when Data changed on Sorting - SwipeListView(react-native-swipe-list-view)

I am using SwipeListView for Listing with Swipe options
I need to sort the list of Items ascending/descending
Sorting functions are done but the list is not refresh
const [productSortList, setProductSortList] = useState(productArraylist);
productArraylist -> main array list from api
productSortList -> temporary array list to store sorting data
<SwipeListView
//useFlatList={true}
ListEmptyComponent={FlatlistEmpty()}
showsVerticalScrollIndicator={false}
// useNativeDriver={false}
keyExtractor={(item, index) => item.id}
data={productSortList}
renderItem={renderProduct}
renderHiddenItem={renderHiddenItem1}
// leftOpenValue={73}
rightOpenValue={-345}
previewRowKey={productSortList[0].id}
previewOpenValue={-400}
previewOpenDelay={1000}
extraData={productSortList}
// onRowDidOpen={onItemOpen}
/>
In FlatList extraData={Our List Array} will do the refresh when the data get change.
How to do with SwipeListView

React Native Action Button - Unable to Add buttons Dynamically

Unable to Add ActionButton Items dynamically.
I have the following setup --
<ActionButton>
<ActionButton.item name={constant_btn1} />
<ActionButton.item name={constant_btn2} />
</ActionButton>
I want to add dynamic buttons to this list. (The list is received from backend)
I have created a function that returns me views of these buttons.
getDynamicBtns() {
return dynamicButtonsList.map(item, key) => {(
return <ActionButton.item name={item.btnName} />;
)};
}
and I have used it in this way -->
<ActionButton>
<ActionButton.item name={constant_btn1} />
<ActionButton.item name={constant_btn2} />
{this.getDynamicBtns()}
</ActionButton>
So this is rendering my constant buttons, but not the dynamic buttons.
EDIT -
I am returning the map from the getDynamicBtns() function and calling invoking the function call too from within render(). This is just some simplified sample code that I have wriiten.
EDIT2 -
To prevent any confusion, changing original question's code.
I figured it out.
The problem was that the .map function returns an array of Objects.
So the final element that was going to be rendered was a React element ActionButton.
The ActionButton had only 3 children, irrespective of the size of my dynamic list.
ActionButton.children: [
staticButton1,
staticButton2,
[dynamicButton1, dynamicButton2, dynamicButton3, ....]
];
As a solution, I took them into separate lists and found a union of the lists.
And then rendered the list inside <ActionButton>
Something like this ->
let listA = [<ActionButton.Item name='staticBtn1.name' />];
let listB = this.getDynamicBtns();
let finalList = _.union(listA, listB);
And then rendered it as -->
<ActionButton>
{finalList}
</ActionButton>
You are no returning anything in getDynamicBtns function. You should return the result of your map:
getDynamicBtns() {
return dynamicButtonsList.map(item => <ActionButton.item name={item.btnName} />)
}

React-native - How to create a scrollable flatList in which the chosen item is the one at the middle?

I would like to create a scrollable FlatList to select only one item among a list. After the user scroll the list, the selected item will be the one in the colored rectangle (which have a fixed position) as you can see here :
Actually I'm only able to render a basic FlatList even after some researches.
Do you know how I should do that ?
I found the solution (but it's not a FlatList) !
To do that I use :
https://github.com/veizz/react-native-picker-scrollview.
To define the background of the current selected items I added a new props highLightBackgroundColor in the ScrollPicker Class in the index file of react-native-picker-scrollview :
render(){
...
let highLightBackgroundColor = this.props.highLightBackgroundColor || '#FFFFFF';
...
let highlightStyle = {
...
backgroundColor: highLightBackgroundColor,
};
...
How to use it :
<ScrollPicker
ref={sp => {
this.sp = sp;
}}
dataSource={['a', 'b', 'c', 'd', 'e']}
selectedIndex={0}
itemHeight={50}
wrapperHeight={250}
highLightBackgroundColor={'lightgreen'}
renderItem={(data, index, isSelected) => {
return (
<View>
<Text>{data}</Text>
</View>
);
}}
onValueChange={(data, selectedIndex) => {
//
}}
/>
How it looks without others customizations:
You can implement the same setup with the very popular react-native-snap-carousel package, using the vertical prop. No need to use a smaller, poorly documented/unmaintained package for this.

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

How do I render a message when there are no filtered results in React?

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.