How can i get the specific array using Lodash in react js - lodash

How can i get the specific array using Lodash in react js ?
I have an array of objects, 10 topUsers.
data:{
"topUsers":[
{
"user":"foo"
},
{
"user":"bar"
},
{
"user":"mike"
},
{
"user":"jen"
},
{
"user":"carl"
},
{
"user":"ben"
},
{
"user":"tony"
},
{
"user":"mark"
},
{
"user":"peter"
},
{
"user":"jake"
}
]}
and I want to display start from top 5 which is "user":"carl", assume the {idx} is the index of array
I'am try to use the _.map for mapping the data, but for specific index or array I dont have any idea.
<TableBody displayRowCheckbox={false} style={{minHeight: 65}}>
{ _.map(this.state.data.topUsers, (users, idx) => { return(
<TableRow displayBorder={true}>
<TableRowColumn style={{height: 75 , textAlign: 'center'}}>{idx + 1}</TableRowColumn>
<TableRowColumn style={{ justifyContent: 'center', textAlign: 'center' , paddingLeft: '5px' }}>
<Col xs={12}>
<Row>
<Col xs={4} style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<label style={{whiteSpace: 'normal', overflow: 'hidden', textOverflow: 'ellipsis'}}>
{_.get(users, 'users', ' ')}
</label>
</Col>
</Row>
</Col>
</TableRowColumn>
</TableRow>) })}

You can use Array#slice (or lodash's equivalent) to slice the array from an index to the end. So arr.slice(4), will create a new array from the 5th (0 based) item to the end.
Btw - if you want the 5 top items, you need to slice from index 5. Slicing from the 4th index will give you 6 items.
For example:
const topUsers = [{"user":"foo"},{"user":"bar"},{"user":"mike"},{"user":"jen"},{"user":"carl"},{"user":"ben"},{"user":"tony"},{"user":"mark"},{"user":"peter"},{"user":"jake"}];
const result = topUsers.slice(5)
.map(({ user }) => user); // whatever you want to map user into
console.log(result);
And in your case:
<TableBody displayRowCheckbox={false} style={{minHeight: 65}}>
{ this.state.data.topUsers.slice(5).map((users, idx) => { return(
<TableRow displayBorder={true}>
<TableRowColumn style={{height: 75 , textAlign: 'center'}}>{idx + 1}</TableRowColumn>
<TableRowColumn style={{ justifyContent: 'center', textAlign: 'center' , paddingLeft: '5px' }}>
<Col xs={12}>
<Row>
<Col xs={4} style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<label style={{whiteSpace: 'normal', overflow: 'hidden', textOverflow: 'ellipsis'}}>
{_.get(users, 'users', ' ')}
</label>
</Col>
</Row>
</Col>
</TableRowColumn>
</TableRow>) })}

you can try _.slice(array, [start=0], [end=array.length])
To learn more, see enter link description here

Related

React Native onLayout x and y are not correct

I am using the React Native PanResponder class to allow for drag and drop if elements of the screen.
What I have discovered is that the onLayout is not returning the x absolute positions, it's being affected by its parent views and is returning weird results.
For example the current view has 3 columns and the onLayout resides in the middle column. It is returning it's x value as 146.5. Which is not the absolute position.
How would I get the absolute position of the element if it resides in multiple parent views?
// Omitted some code for clarity
const dropZoneValues = React.useRef(null);
const pan = React.useRef(new Animated.ValueXY());
const setDropZoneValues = React.useCallback((event) =>
{
dropZoneValues.current = event.nativeEvent.layout;
}, []);
return (
<Main background={bg} showHeader={false}>
<Row rowStyles={{
textAlign: 'center', marginLeft: 50, marginRight: 50,
alignSelf: 'center',
alignItems: 'center',
textAlignVertical: 'center',
justifyContent: 'center',
}}>
<Col xs={4} sm={4} md={4} lg={4}>
</Col>
<Col xs={4} sm={4} md={4} lg={4}>
<View
onLayout={setDropZoneValues}
style={styles.dropZone}>
<Text style={styles.text}>Drop me here!</Text>
</View>
{renderDraggable()}
</Col>
<Col xs={4} sm={4} md={4} lg={4}>
</Col>
</Row>
</Main>
);
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
padding: 20,
flexDirection: 'column',
},
dropZone: {
height: 100,
backgroundColor: '#2c3e50',
width: 100,
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
},
text: {
marginTop: 25,
marginLeft: 5,
marginRight: 5,
textAlign: 'center',
color: '#fff'
},
draggableContainer: {
zIndex: 99999
},
circle: {
backgroundColor: '#1abc9c',
width: 80,
height: 80,
borderRadius: CIRCLE_RADIUS,
zIndex: 99999,
position: 'absolute'
}
});
onLayout returns positions relative to parents. You can instead use event.target.measure within the onLayout callback to find the absolute position (though note this is marginally worse for performance).
<MyComponent
onLayout={(event) => {
event.target.measure(
(x, y, width, height, pageX, pageY) => {
doSomethingWithAbsolutePosition({
x: pageX,
y: pageY,
});
},
);
}}
/>
(hat tip to https://stackoverflow.com/a/64882955/842506)

how to use inline flex property in react native

Here's what I'm trying to achieve:
I want to display inline all these three elements inside each Block.
Here's what I have done so far:
export default function App() {
const cheers = [
'cheers',
'high five'
]
return (
<Block style={{ flex: 1,
flexDirection: "row",
alignContent: "space-between",
marginTop: 50}}
>
<Block style={{ flex: 2, justifyContent: 'center'}}>
<Text style={{marginRight: 5}}>Send a</Text>
</Block>
<Block style={[styles.dropdownsRow, {flex: 2}]}>
<SelectDropdownMenu
data={cheers}
onSelect={(selectedItem, index) => {
console.log(selectedItem, index);
}}
defaultButtonText={'Cheers'}
buttonTextAfterSelection={(selectedItem, index) => {
return selectedItem.name;
}}
rowTextForSelection={(item, index) => {
return item.name;
}}
buttonStyle={styles.dropdown1BtnStyle}
buttonTextStyle={styles.dropdown1BtnTxtStyle}
renderDropdownIcon={isOpened => {
return <FontAwesome name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#8898aa'} size={10} />;
}}
dropdownIconPosition={'right'}
dropdownStyle={styles.dropdown1DropdownStyle}
rowStyle={styles.dropdown1RowStyle}
rowTextStyle={styles.dropdown1RowTxtStyle}
/>
</Block>
<Block style={{flex: 2, justifyContent: 'center' }}>
<Text style={{marginLeft: 5, marginRight: 5}}>to</Text>
</Block>
<Block style={{ justifyContent: 'center'}}>
<Input
right placeholder="Type your custom question here."
iconContent={<Block />}
/>
</Block>
);
}
const styles = StyleSheet.create({
dropdownsRow: {justifyContent: 'center', maxWidth: '10%'},
dropdown1BtnStyle: {
height: 45,
backgroundColor: '#edeff2',
borderRadius: 5,
borderColor: '#444',
},
dropdown1BtnTxtStyle: {color: '#8898aa', textAlign: 'left', fontSize: 14},
dropdown1DropdownStyle: {backgroundColor: '#EFEFEF'},
dropdown1RowStyle: {backgroundColor: '#EFEFEF', borderBottomColor: '#C5C5C5'},
dropdown1RowTxtStyle: {color: '#444', textAlign: 'left'}
});
I'm new to react native and don't know how flex property works.
Here's my sample output:
The whole code found here whole code
You can use Yoga layout website to find your desired UI and then migrate your styles to your code.

RN: Align items in a row both left and right

Here is RN (0.59) component using sectionList to display an event name in a row. The renderItem renders 3 items in a row, starting with a head image (left image), then event name, ending with another head image (right image).
render() {
return (
<View style={styles.container}>
<SectionList
sections={this.state.activeEvents}
renderItem={({item, section}) => {return (
<View style={styles.container}>
<Image style={styles.image} source={{uri: item.image}}/>
<TouchableOpacity onPress={() => {this._onPress(item.id)}} >
<Text style={styles.item} key={item.id}>{item.name}</Text>
</TouchableOpacity>
<View style={styles.containerRight}>
<Image style={styles.image} source={{uri: "https://bootdey.com/img/Content/avatar/avatar1.png"}}/>
</View>
</View>)}}
renderSectionHeader={({section}) => <Text style={styles.sectionHeader}>{section.title}</Text>}
keyExtractor={(item, index) => item + index}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22,
paddingVertical: 12,
flexDirection: 'row',
alignItems: 'flex-start',
flexDirection: 'row',
alignItems: 'flex-start'
},
containerRight: {
flex: 1,
paddingTop: 22,
paddingVertical: 12,
flexDirection: 'row',
alignItems: 'flex-end',
flexDirection: 'row',
alignItems: 'flex-end'
},
sectionHeader1: {
paddingTop: 2,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 2,
fontSize: 14,
fontWeight: 'bold',
backgroundColor: 'rgba(247,247,247,1.0)',
},
sectionHeader:{
backgroundColor : '#64B5F6',
fontSize : 20,
padding: 5,
color: '#fff',
fontWeight: 'bold'
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
image:{
width:45,
height:45,
borderRadius:20,
marginLeft:20
},
imageRight:{
width:45,
height:45,
borderRadius:20,
marginRight:20
},
})
Here is the output of the above render:
All row items (left image, event name, right image) should be vertically aligned. The left image and event name are properly aligned to the left side of the row, but the right image should be horizontally aligned to the right side of the row. How can I change my jsx and styling to achieve this UI?
I suppose you'd like something like this:
You can accomplish this by adding a big container for the row and adding:
justifyContent: 'space-between'
Wrap the source code and fix it to your needs or see a working snack: snack.expo.io/#abranhe/stackoverflow-56638124
import React, { Component } from 'react';
import {
SectionList,
Text,
Image,
View,
TouchableOpacity,
StyleSheet,
} from 'react-native';
const events = [
{
title: '2019-04-03',
data: [
{
name: 'Event 1',
imageLeft: {
uri: 'https://bootdey.com/img/Content/avatar/avatar1.png',
},
imageRight: {
uri: 'https://bootdey.com/img/Content/avatar/avatar2.png',
},
},
{
name: 'Event 2',
imageLeft: {
uri: 'https://bootdey.com/img/Content/avatar/avatar3.png',
},
imageRight: {
uri: 'https://bootdey.com/img/Content/avatar/avatar4.png',
},
},
],
},
{
title: '2019-04-07',
data: [
{
name: 'Event 2',
imageLeft: {
uri: 'https://bootdey.com/img/Content/avatar/avatar5.png',
},
imageRight: {
uri: 'https://bootdey.com/img/Content/avatar/avatar6.png',
},
},
],
},
];
export default class App extends Component {
onPressEvent = id => {
alert(eventName);
};
render() {
return (
<SectionList
style={styles.selectionList}
sections={events}
renderItem={({ item: event, section }) => {
return (
<View style={styles.container}>
<View style={styles.content}>
<Image style={styles.image} source={event.imageLeft} />
<TouchableOpacity onPress={() => this.onPressEvent(event.name)}>
<Text>{event.name}</Text>
</TouchableOpacity>
<Image style={styles.image} source={event.imageRight} />
</View>
</View>
);
}}
renderSectionHeader={({ section }) => (
<Text style={styles.sectionHeader}>{section.title}</Text>
)}
keyExtractor={(item, index) => item + index}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22,
},
content: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
selectionList: {
marginTop: 22,
},
sectionHeader: {
backgroundColor: '#64B5F6',
fontSize: 20,
padding: 5,
color: '#fff',
fontWeight: 'bold',
},
image: {
width: 45,
height: 45,
borderRadius: 20,
margin: 20,
},
});
If you have any questions let me know!
Update after a comment by the question author
It looks close. But I was not able to do any test since my post because of an error related to AndroidX. Can you move the event.name to the left right after the left image? For the icon on the right, it may be changed to a hamburger menu
It would be easy just wrap the left icon into a
<View>
<Image/>
<Text>Some Text</Text>
</View>
then it would look like this:
See the updated snack: snack.expo.io/#abranhe/stackoverflow-56638124-updated
<View style={styles.leftIcon}>
<Image style={styles.image} source={event.imageLeft} />
<TouchableOpacity onPress={() => this.onPressEvent(event.name)}>
<Text>{event.name}</Text>
</TouchableOpacity>
</View>
And then add the following style:
leftIcon: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}

How to return loop the button 5 times and then return in next row?

I create a <CardItem /> from native-base and style a <Button />. I return the from releasedTime.map() function.
If my releasedTime length < 6. The efficient is what i want.
Here is when releasedTIme length = 5
Here is when eleasedTIme length = 2
If releasedTime is a huge array, it becomes terrible like this
So i want it when map function loop 5 times ,it can be returned in next row.
I have no idea how to do it. I think a {} just can return once.
If write multiple {} how do i know releasedTime loop how many times and use then with multiple {} ?
Any help would be appreciated. Thanks in advance.
Here is my file use <CardItem />
<CardItem>
<Body>
<Image source={{uri: photoHref }} style={{height: 200, width: '100%', resizeMode: 'stretch', flex: 1}}/>
<Body style={{ flex: 1, flexDirection: 'row', alignSelf: 'flex-start', paddingTop: 5, flexWrap: 'wrap', width: '100%' }}>
{releasedTime.map(value => {
return (
<Button key={value}>{`${hour}:${minute}`}</Button>
);
})}
</Body>
</Body>
</CardItem>
My <Button /> from:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
const Button = ({ onPress, children }) => {
const { buttonStyle, textStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
const styles = {
textStyle: {
alignSelf: 'center',
color: '#007aff',
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10
},
buttonStyle: {
flex: 1,
alignSelf: 'stretch',
backgroundColor: '#fff',
borderRadius: 5,
borderWidth: 1,
borderColor: '#007aff',
marginLeft: 5,
marginRight: 5
}
};
export { Button };
I try caculate the index, it is still no wroking :(
<CardItem>
<Body>
<Image source={{uri: photoHref }} style={{height: 200, width: '100%', resizeMode: 'stretch', flex: 1}}/>
<Body style={{ flex: 1, justifyContent: 'flex-start',flexDirection: 'row', paddingTop: 5, flexWrap: 'wrap', width: '100%' }}>
{releasedTime.map((value, index) => {
if( index / 5 <= 1) {
return (
<Button key={index}>{`${hour}:${minute}`}</Button>
);
} else {
return (
<Body style={{ flex: 1, justifyContent: 'flex-start',flexDirection: 'row', paddingTop: 5, flexWrap: 'wrap', width: '100%' }}>
<Button key={index}>{`${hour}:${minute}`}</Button>
</Body>
);
}
})}
</Body>
</Body>
</CardItem>
You can use the index of the map function to determine, if there are 5 or more elements inside the array and insert a newline or style the button differently on a new row.
I am not on an PC with IDE, but something like this should point you in the right direction:
{releasedTime.map((value, index) => {
if (index > 5) return <ButtonOnNewLine>...</ButtonOnNewLine>
return (
<Button>...</Button>
);
})}
You can also do the styling of the button related to the index with a modulo.
Or do it like in this codepen with pure css:
https://codepen.io/SakerONE/pen/bdbLNz
Do you get the concept?

Can I use autoGrow in redux form?

I am wondering if I can use autoGrow in redux form or I should use something else?
Here is my render code
const renderField = ({ label, keyboardType, name, meta: { touched, error }, input: {onChange, ...restInput} }) => {
return (
<View style={{flexDirection: 'column', height: 70, alignItems: 'flex-start'}}>
<View style={{flexDirection: 'row', height: 30, alignItems: 'center', borderColor: 'black', borderBottomWidth: 1,}}>
<TextInput style={{ height: 37, width: 280, paddingLeft: 10, fontSize: 20}}
keyboardType={keyboardType} onChangeText={onChange} {...restInput}
placeholder={label}
>
</TextInput>
</View>
{touched && ((error && <Text style={{color: 'red', }}>{error}</Text>))}
</View>);
};
You can use textArea to change the the number of rows and to expand the text area
const renderTextArea = ({ input, label, className, rows, meta: { touched, error, warning }}) => (
<div>
<div>
<textarea {...input} placeholder={label} rows={rows} cols="100" className={className}/>
{touched && ((error && <span className="error_field">{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
)