quick replies press function (gifted chat) react native - reactjs

I have worked on a chat app and I want to make a function when the user tab on one of these replies showed as user message in chat UI, and I want to know which quick reply he choose , anyone helps me?
this is code below:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
class App extends Component {
state ={
messages: [
{
_id: 1,
text: 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT',
createdAt: new Date(),
user: {
_id: 2,
name: 'FAQ Bot',
avatar: 'https://i.imgur.com/7k12EPD.png'
},
quickReplies: {
type: 'radio', // or 'checkbox',
keepIt: true,
values: [
{
title: '😋 Yes',
value: 'yes',
},
{
title: '📷 Yes, let me show you with a picture!',
value: 'yes_picture',
},
{
title: '😞 Nope. What?',
value: 'no',
},
],
}
}
]
};
//................
onSend(messages = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages)
}));
}
onSend(quickReply = []) {
this.setState(previousState => ({
quickReply: GiftedChat.append(previousState.quickReply, quickReply)
}));
}
/*onSend(suggestions = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.suggestions, suggestions)
}));
}*/
render() {
return (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<GiftedChat
messages={this.state.messages}
quickReply={this.state.messages.quickReplies}
//messages={this.state.suggestions}
onSend={messages => this.onSend(messages)}
onQuickReply={quickReply => this.onQuickReply(quickReply)}
//onSend2={suggestions => this.onSend2(suggestions)}
user={{
_id: 1
}}
/>
</View>
);
}
}
export default App;
showed as user message in chat UI, and I want to know which quick reply he choose, anyone helps me?

You can get the chosen quick reply. And pass into chat.
onQuickReply(quickReply) {
if(quickReply[0].value == "yes") {
} else if (quickReply[0].value == "yes_picture") {
} else if (quickReply[0].value == "NO") {
}
let message = quickReply[0].value;
let msg = {
_id: this.state.messages.length + 1,
text: message,
createdAt: new Date(),
user: {
_id:1
}
}
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, [msg])
}));
var sendBotResponsetxt = "Thanks";
this.sendBotResponse(sendBotResponsetxt);
}

Related

Using find and map together React

We have chat app build on React
const Chat = ({ thread }) => {
return (
<div className='thread'>
{thread.map((message, index) =>
<Message message={message} key={index} repliedMessage={message}/>
)}
</div>
);
};
export default class App extends React.Component {
state = {
thread: [
{
id: 1,
user: 'John',
text: 'Hellow'
},
{
id: 2,
user: 'Jim',
replyTo: 1,
text: 'Hi'
},
{
id: 3,
user: 'Jack',
replyTo: 2,
text: 'Cheers :)'
}
]
};
App must show what message have been replied.
The question is - how I can use FIND method with MAP in Chat component?
I don't think you need to use the find method here:
thread.map((message, index) => {
if(message.replyTo) {
return ...
} else {
return ...
}
}
)

React console.log not showing array values

Console it printing Array [] instead of values. I have checked the code but figure it out. Why doesn't console.log show me array values when i click button?
import React from "react";
import { StyleSheet, View, FlatList } from "react-native";
import DataManager from "../config/DataManager";
const getMemories = () => {
let commonData = DataManager.getInstance();
let user = commonData.getUserID();
return commonData.getMemories(user);
}
function MemoriesScreen(props) {
const memoryList = getMemories();
console.log(memoryList);
return (
<AppScreen style={styles.container}>
<FlatList
data={memoryList}
keyExtractor = {memory => memory.memoryid.toString()}
renderItem = {({item}) =>
<AppCard
title={item.title}
subtitle={item.subtitle}
image={item.image}
category={item.category}
/>}
/>
</AppScreen>
);
}
const styles = StyleSheet.create({
container:{
backgroundColor:AppColors.otherColor,
flex:1,
marginTop:0,
},
})
export default MemoriesScreen;
this the DataManger js screen
export default class DataManager {
static myInstance = null;
userID = "";
memories = [
{
userid: "user1",
memoryid: 1,
title: "Memories of School days",
subtitle: "Created on 3rd of January, 2005",
image: require("../assets/School-days.jpeg"),
category: "Childhood",
},
{
userid: "user1",
memoryid: 2,
title: "Memories of School days",
subtitle: "Created on 3rd of January, 2005",
image: require("../assets/School-days.jpeg"),
category: "Childhood",
},
{
userid: "user2",
memoryid: 1,
title: "Memories of School days",
subtitle: "Created on 3rd of January, 2005",
image: require("../assets/School-days.jpeg"),
category: "Childhood",
}
];
static getInstance() {
if (DataManager.myInstance == null) {
DataManager.myInstance = new DataManager();
}
return this.myInstance;
}
getUserID() {
return this.userID;
}
setUserID(id) {
this.userID = id;
}
getMemories(id) {
return this.memories.filter((memory) => memory.userid === id);
}
addMemory(memory){
this.memories.push(memory);
}
}
Your array can be empty. Push something before log and check your array like this.
memoryList.push("test memory");
console.log(memoryList);

Testing zustand state changes caused by a component in Jest

I am pretty new to using jest and Im trying to test a component that makes a state change which acts upon my global state (using Zustand). Basically im clicking a button and its adding an item to my state.traits. Here is my component code:
import { Flex, useToast } from '#chakra-ui/react'
import { FC } from 'react'
import { useProfileStore } from 'stores/profileStore'
interface DataTrait {
name: string,
id: string
}
type Props = {
trait: DataTrait
}
export const ChipItem: FC<Props> = ({ trait }) => {
const { traits, setTraits } = useProfileStore()
const toast = useToast()
const traitNames = traits.map((trait) => trait.name)
const emptyTraits = traits.filter((trait) => trait.name === "")
const handleClick = (trait: DataTrait) => {
if (!traitNames.includes(trait.name) && emptyTraits.length !== 0) {
let currentItem = traits.filter(trait => trait.name === "")[0]
let items = [...traits]
let item = {position: currentItem.position, id: trait.id, name: trait.name}
items[items.indexOf(currentItem)] = item
setTraits(items)
} else if (emptyTraits.length === 0){
toast({
title: 'Error',
status: 'error',
description: 'Only 5 traits can be selected',
isClosable: true,
duration: 5000
})
} else {
toast({
title: 'Error',
status: 'error',
description: 'Please select unique traits',
isClosable: true,
duration: 5000
})
}
}
return (
traitNames.includes(trait.name) ? (
<Flex mx={4} p={2} cursor="pointer" borderRadius="20px" backgroundColor="green" borderWidth="1px" borderColor="white" textColor="white" onClick={() => handleClick(trait)}>{trait.name}</Flex>
) : (
<Flex mx={4} p={2} cursor="pointer" borderRadius="20px" borderWidth="1px" borderColor="grey" onClick={() => handleClick(trait)}>{trait.name}</Flex>
)
)
}
here is my store code:
import create from 'zustand'
export interface Trait {
position: string,
name: string,
id: string,
}
export type Traits = Trait[]
const initialTraits = [
{position: "0", name: "", id: ""},
{position: "1", name: "", id: ""},
{position: "2", name: "", id: ""},
{position: "3", name: "", id: ""},
{position: "4", name: "", id: ""},
]
export type ProfileStore = {
traits: Traits;
setTraits: (traits: Traits) => void;
clearTraits: () => void;
}
export const useProfileStore = create<ProfileStore>((set) => ({
traits: initialTraits,
setTraits: (traits) => set({ traits }),
clearTraits: () => set({ traits: initialTraits })
}))
and here is my test code:
import React from 'react';
import { ChipItem } from "../../ChipList/ChipItem";
import { act, render, renderHook } from "#testing-library/react";
import { useProfileStore } from "../../../stores/profileStore";
const stubbedTrait = {
name: "Doing Work",
id: "efepofkwpeok"
}
it("displays the trait chip", () => {
const { queryByText } = render(<ChipItem trait={stubbedTrait} />);
expect(queryByText("Doing Work")).toBeTruthy();
})
it("sets the chip information in the store", () => {
act(() => {
const { traits } = renderHook(() => useProfileStore())
const { getByText } = render(<ChipItem trait={stubbedTrait}/>);
getByText(stubbedTrait.name).click()
expect(traits.includes(stubbedTrait)).toBeTruthy()
})
})
whats happening, is that it keeps telling me that renderHook is not a function and traits always comes back undefined. any help would be greatly appreciated!
Currently you must install and import React Testing Hooks separately
The best way to unit test Zustand state changes inside and specific component is not by using Zustand but by mocking the store hook with Jest.
You should create a test case for the Zustand Store using React Hook Testing library and once you verify the hook behaves as expected, then you mock the store with manual traits and setTraits changes.
Once you have the unit tests then you should test the behaviour of the real hook and components together with integration tests.

Why am I getting undefined after loading the page? But after refreshing the current page, I get normal data. How can I fix it? [duplicate]

This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 2 years ago.
I'm gettin undefined in hubConnection, and my program doesn't work, but after refreshing everything works correctly. I've tried to make hubConnection as simple property, but it didn't help me. One more thing that I've already tried is to create useRef hook and check if hubConnection if not undefined, if it not, then block the useEffect, but my messages after this action has stopped work.
Code of the program:
import React, { useCallback, useState, useEffect, useContext } from "react";
import { View, StyleSheet } from "react-native";
import { routes } from "../../../../Environment";
import { Icon } from 'react-native-elements'
import Font from "../../../data/fonts/Font";
import { GiftedChat, Bubble, Send, InputToolbar } from 'react-native-gifted-chat'
import { container } from 'tsyringe';
import ChatService from "../../../../api-service/chat-service/ChatService";
import { AuthContext } from "../../auth/AuthProvider";
import { HubConnection, HubConnectionBuilder } from "#microsoft/signalr";
const Chat = (props: any) => {
const chatService = container.resolve(ChatService);
const [messages, setMessages] = useState([]);
const [message, setMessage] = useState("");
const [hubConnection, setHubConnection] = useState<HubConnection>();
const { user } = useContext(AuthContext);
const getRandomInt = (max: number) => {
return Math.floor(Math.random() * Math.floor(max));
}
useEffect(() => {
setMessages([
{
_id: 1,
text: 'Hello dude',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
{
_id: 2,
text: 'Hello Tom',
createdAt: new Date(),
user: {
_id: user?.id.toString()!,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
{
_id: 3,
text: 'How are you?',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
])
const hubConnectionFunc = new HubConnectionBuilder()
.withUrl(routes.chatUrl)
.build();
hubConnectionFunc?.start().then(() => "Connection started!");
hubConnectionFunc.on("RecieveMessage", message => {
console.log(messages[0].text);
setMessages(previousMessages => GiftedChat.append(previousMessages, {
_id: getRandomInt(10000),
text: message,
createdAt: new Date(),
user: {
_id: user?.id.toString()!,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
}))
})
setHubConnection(hubConnectionFunc);
console.log(hubConnection);
}, [])
const onSend = useCallback((messages = []) => {
hubConnection?.invoke("SendMessage", messages[0].text)
.catch((err: any) => console.log(err));
setMessage("");
}, [])
const renderBubble = (props: any) => {
return (
<Bubble
{...props}
wrapperStyle={{
left: {
backgroundColor: "#F1F1F4",
},
right: {
backgroundColor: "#EB7A89"
}
}}
textStyle={{
left: {
color: "#000000"
},
right: {
color: "#FFFFFF"
}
}}
/>
);
}
const renderSend = (props: any) => {
return (
<Send {...props}>
<View style={styles.button}>
<Icon
name='paper-plane'
type='font-awesome'
color='white'
/>
</View>
</Send>
)
}
const renderInputToolbar = (props: any) => {
return (
<InputToolbar {...props} primaryStyle={{
borderWidth: 2,
justifyContent: "center",
alignItems: "center",
height: 44
}}
/>
)
}
return (
<View style={styles.chatWrapper}>
<GiftedChat
placeholder="Aa"
renderTime={() => <View></View>}
maxInputLength={500}
messages={messages}
onInputTextChanged={setMessage}
text={message}
onSend={onSend}
scrollToBottom
alwaysShowSend
user={{
_id: user?.id.toString()!,
name: user?.name!,
}}
renderBubble={renderBubble}
renderSend={renderSend}
renderInputToolbar={renderInputToolbar}
/>
</View >
)
}
NodeJS console after first loading
NodeJS console after refreshing the page
Some of your data not Loading 1st time but when you refresh your screen again it loads your data to fix this issue you can use async-await or && logic

set Highstock xAxis range within options object

My React components pulls data for an API. The options.series.data data for the yAxis is what receives the API data.
The component is enabled to pull the data range for day/hour/minute which comes with a datestamp for when the data was recorded. How do I dynamically set the xAxis min/max range to respect the day/hour/minute duration change?
The HighchartsReact instance receives the data series via the options object that's where I'd like to setup the dynamic xAxis handler method. Perhaps it's setExtemes().
The component code is below.
import React, { Fragment, useState, useEffect } from 'react';
import { connect } from 'react-redux';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import highchartsStockChart from 'highcharts/modules/stock';
import { getDaily, getHourly, getMinute } from '../actions/getData';
import Spinner from './Spinner';
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
highchartsStockChart(Highcharts);
const Chart = ({
match,
list: { list, loading },
getDaily,
getHourly,
getMinute,
error
}) => {
const [method, setMethod] = useState(() => getDaily);
useEffect(() => {
method(match.params.currency.toUpperCase(), 30);
}, [match.params.currency, method]);
console.log('Chart.js list:', list);
console.log('Chart.js error:', error);
console.log('Chart.js loading:', loading);
const options = {
title: {
text: 'Close Price'
},
series: [{
name: 'close price',
data: list.map(item => item.close),
tooltip: {
pointFormat: 'close price: ${point.y:,.2f}'
},
animation: false
}],
scrollbar: {
enabled: false
},
navigator: {
enabled: false
},
rangeSelector: {
inputEnabled: false,
allButtonsEnabled: true,
buttonSpacing: 10,
buttonPosition: {
align: 'left'
},
buttons: [{
type: 'day',
count: 1,
text: 'Day',
events: {
click: () => setMethod(() => getDaily)
}
}, {
type: 'hour',
count: 1,
text: 'Hour',
events: {
click: () => setMethod(() => getHourly)
}
}, {
type: 'minute',
count: 1,
text: 'Minute',
events: {
click: () => setMethod(() => getMinute)
}
}]
}
};
let content;
if (error && error.message) {
content = error.message;
} else if (!list.length || loading) {
content = <Spinner />;
} else {
content = (
<Fragment>
{list.map(item => <span key={item.time}>{item.close} </span>)}
<button onClick={() => setMethod(() => getHourly)}>set Hourly</button>
<button onClick={() => setMethod(() => getMinute)}>set Minute</button>
<HighchartsReact
highcharts={Highcharts}
options={options}
constructorType={'stockChart'}
/>
</Fragment>
);
}
return (
<div>
Chart.
{content}
</div>
);
};
const mapStateToProps = state => ({
list: state.data,
error: state.error
});
export default connect(mapStateToProps, { getDaily, getHourly, getMinute })(Chart);
You can:
use chart redraw event callback function and call setExtremes:
chart: {
events: {
redraw: function() {
if (allowChartRedraw) {
allowChartRedraw = false;
this.xAxis[0].setExtremes(0, Math.random() * 3);
}
allowChartRedraw = true;
}
}
}
Live example: http://jsfiddle.net/BlackLabel/wvpnct9h/
API Reference: https://api.highcharts.com/highcharts/chart.events.redraw
keep all of the options in a state and manipulate axis extremes by min and max properties:
componentDidMount() {
this.setState({
chartOptions: {
series: [
{
data: [Math.random() * 3, Math.random() * 3, Math.random() * 3]
}
],
xAxis: {
min: 0,
max: Math.random() * 3
}
}
});
}
Live demo: https://codesandbox.io/s/highcharts-react-demo-jo6nw
get the chart reference and call setExtremes on the xAxis.
Docs: https://github.com/highcharts/highcharts-react#how-to-get-a-chart-instance

Resources