How to get the position of a moving element in React Native - javascript

I am currently trying to develop an app with draggable elements using React Native and the library react Native draggable (https://www.npmjs.com/package/react-native-draggable).
My goal is to get the position of my Draggable element. (So I can change their color depending on where it is on the screen).
I tried different method but nothing worked for me. Here is the last thing I tried :
return (
<View>
<Draggable
onDragRelease={event =>
{const layout = event.nativeEvent.layout;
console.log('x:', layout.x);
console.log('y:', layout.y);
}
}
x={positionX}
y={positionY}
renderSize={56}
renderColor='#BDFF00'
renderText={'Drag me'}
// onDrag={getPosition}
/>
</View>
)
The code above returns this error (TypeError: undefined is not an object (evaluating 'layout.x'))
I also tried to do this :
const getPosition = (event) => {
console.log(event.locationX)
setPositionX(event.locationX)
setPositionY(event.locationY)
};
const changerColorFunction = () => {
}
return (
<View>
<Draggable
x={positionX}
y={positionY}
renderSize={56}
renderColor='#BDFF00'
renderText={'Drag me'}
onDrag={getPosition}
/>
</View>
)
Based on the react native Draggable documentation, but it is not working too. I think, I didn't fully understand how it should be working. Any help would be great.

Related

React Native - Disable nested scrolling

I have a parent FlatList which, in its footer, can render another flatlist or a simple scroll view.
const renderFooter1 = () => {
return <ScrollView> ... </ScrollView>;
}
const renderFooter2 = () => {
return <FlatList ... />;
}
// Note: I am not doing this in real life, just an example for handling both possible footers
return (
<FlatList
refreshControl={renderRefreshControl()}
ListHeaderComponent={renderHeader()}
ListFooterComponent={Math.random() * 10 > 0.5 ? renderFooter1() : renderFooter2()}
showsVerticalScrollIndicator={false}
/>
);
The problem I am experiencing is that, sometimes, when scrolling down, the component which scrolls is the footer, and not the parent list.
How can I avoid that behavior?
You can add the prop scrollEnabled={false} to whichever FlatList you don't want to scroll.

React-dnd multiple elements

I can make react-dnd drag easily having a single element to drag over however I have array of 4 fields I'd like to make draggable. In my example code down below it creates four boxes from mapping the array and each box has a className of 'element'. Which should make them all draggable however they won't move.
Here is my drag code:
const ELEMENT = 'element';
const [{ isDragging }, drag, dragPreview] = useDrag(() => ({
type: ELEMENT,
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
}))
Here is my draggable element:
{FieldDetail.map((e,i) =>
<div key={i} ref={dragPreview} style={{ opacity: isDragging ? 0.5 : 1}}>
<div className='element' ref={drag}></div>
</div>
)}
Any ideas? Do I need to do something more within the type or className?
I had a similar problem - I discovered that you can call drag(ref) to take an ordinary ref and link it up with DnD.
For your use case, I would try pre-allocating the refs and calling drag on each one:
// generate refs
const refs = FieldDetal.map(x => useRef());
// call drag on each ref, linking it up with React DnD
refs.forEach(x => drag(x));
// And then when you render your component, use the refs
{FieldDetail.map((e,i) =>
<div key={i} ref={dragPreview} style={{ opacity: isDragging ? 0.5 : 1}}>
<div className='element' ref={refs[i]}></div>
</div>
)}
Not tested but this general idea should get you where you need to be. You can even make something both a drag and a drop target by calling drop(drag(ref)).

How do you render item time under bubble chat react native gifted chat?

I use React Native Gifted Chat To create a UI chat and I want to render the chat time and symbol under the bubble chat.
I want make like this image :
I have tried to use the rendering message but no luck, please help.
I was just working on this my self. What you need to do is to have custom renderBubble in which you wrap the with your own components. It would look something like this. The first part of the code is just the alignment of timestamp to the left or right, depending if the message was written by the current user or not.
renderBubble(props) {
var sameUserInPrevMessage = false;
if (props.previousMessage.user !== undefined && props.previousMessage.user) {
props.previousMessage.user._id === props.currentMessage.user._id ? sameUserInPrevMessage = true : sameUserInPrevMessage = false;
}
var messageBelongsToCurrentUser = currentUserId == props.currentMessage.user._id;
return (
<View>
{!sameUserInPrevMessage && <View
style={messageBelongsToCurrentUser ? styles.messageTimeAndNameContainerRight : styles.messageTimeAndNameContainerLeft}
>
<Bubble
{...props}
/>
<Text style={styles.messageTime}>{moment(props.currentMessage.createdAt).format("LT")}</Text>
<Text style={styles.messageUsername}>{props.currentMessage.user.name}</Text>
</View>}
</View>
)
}
also put this in the GiftedChat component renderMessage={this.renderBubble}

How to render something in an if statement React Native

Problem
I am using a flatlist in react native, and want to compare to variables in the flatlist, and render a text component if the two variables are equal, but render nothing if they are not. I've tried many methods of doing this, but they nothing has worked. I would love some help figuring out a way to do this! Thank you.
Couple ways that spring to mind straight away. Ill just assume what you are trying to compare but you can switch these variables out for whatever you please. First thing you could do is have your text be conditional inside of your Text component, EG
<Text>{this.state.variable == this.props.stuff ? "RENDER TEXT" : ""}</Text>
or, if you want to emit the Text component when variables are not equal, have a function inside of your class that will return the Text component conditionally
renderMessage = () => {
if(this.state.variable == "stuff"){
return(
<Text>They were equal</Text>
);
}else{
return(
<View></View> // OR WHATEVER YOU WANT HERE
);
}
}
...
//Then in your render function
....
<View style = {styles.whatever}>
{this.renderMessage()}
</View>
just compare your data in renderItem method accordingly
<FlatList
data={this.props.data}
renderItem={this._renderItem}
/>
_renderItem = ({item}) => (
if(item=='somthing'){
return <Text> your test </Text>
}else{
return <Text>some other text</Text>
}
);
if you want to compare your text in component then
<View>
{
item.data == 'somthing'
?
<Text>if</Text>
:
<Text>else</Text>
}
</View>

Dynamic row heights with react-virtualized and new CellMeasurer

I'm using react-virualized 9 with Autosizer, List, and CellMeasurer components. I need to update the row heights when the list data has changed. It appears that since the changes to support React Fiber in version 9 the only public method for CellMeasurer is now measure(). Most of the examples use the previous resetMeasurementForRow() method. The current CellMeasurer doc doesn't seem to have any info on the new public methods. Not sure if I've overlooked something but any help is appreciated.
const cache = new CellMeasurerCache({
defaultHeight: 60,
fixedWidth: true
});
<AutoSizer>
{({ width, height }) => (
<List
deferredMeasurementCache={cache}
height={height}
ref={element => { this.list = element; }}
rowCount={list.length}
rowHeight={cache.rowHeight}
rowRenderer={this.rowRenderer}
width={width}
/>
)}
</AutoSizer>
rowRenderer({ index, key, parent, style }) {
return (
<CellMeasurer
cache={cache}
columnIndex={0}
key={key}
overscanRowCount={10}
parent={parent}
ref={element => { this.cellMeasurer = element; }}
rowIndex={index}
>
{({ measure }) => {
this.measure = measure.bind(this);
return <MyList index={index} data={list[index]} style={style} />;
}}
</CellMeasurer>
);
}
componentWillReceiveProps(nextProps) {
// Some change in data occurred, I'll probably use Immutable.js here
if (this.props.list.length !== nextProps.list.length) {
this.measure();
this.list.recomputeRowHeights();
}
}
I need to update the row heights when the list data has changed.
The current CellMeasurer doc doesn't seem to have any info on the new public methods.
Admittedly the docs could be improved, with regard to the new CellMeasurer. In this case though, you need to do 2 things in respond to your row data/sizes changing:
If a specific list-item has changed size then you need to clear its cached size so it can be remeasured. You do this by calling clear(index) on CellMeasurerCache. (Pass the index of the row that's changed.)
Next you'll need to let List know that its size information needs to be recalculated. You do this by calling recomputeRowHeights(index). (Pass the index of the row that's changed.)
For an example of something similar to what you're describing, check out the example Twitter-like app I built with react-virtualized. You can see the source here.
if (this.props.list.length !== nextProps.list.length) {
cache.clearAll();
}
This helped me! :)

Categories