Using find and map together React - reactjs

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 ...
}
}
)

Related

React state not updating on second index

I have nested objects as described below and updating states.
`
interface BookState {
name: string
authors: AuthorState[]
}
interface AuthorState {
name: string
}
const [bookValues, setBookValues] = useState<BookState[]>(bookStateInitial)
// Add new empty author; which will later be filled from textfields
const onClickAddAuthor = (bookIndex: number) => {
let newAuthor = { } as AuthorState
let authors = [...bookValues[bookIndex].authors, newAuthor]
let newBookState = update(bookValues, { [bookIndex]: { authors: { $set: authors } } })
setBookValues(newBookState) // ** edited
}
// somewhere i populate bookValues as:
bookValues = [
{name: "Book-1", authors: [{name: "Author-1"}] },
{name: "Book-2", authors: [{name: "Author-1"}, {name: "Author-2"}]}
]
`
When I add an author, suppose in "Book-1" index 0, I call the onClickAddAuthor(0), the state updates and UI updates. But when I add an author, suppose in "Book-2" index 1, i call the onClickAddAuthor(1), the state value can be seen updating when printing to console but the UI does not update. I am using https://github.com/kolodny/immutability-helper to update the state.
I expect to add a new empty author on index-1 as well, which should update the state and UI. I tried making deep copies of the book Values and updating the state with that, but it is not working. If it is working in index 0, it should work on other indexes (1, 2, 3 .. ) as well. I am not able to understand.
I tested the posted code with 4 items in bookValues, it seems that the onClickAddAuthor is working as expected. Perhaps the output logic could be checked to see if it updates correctly.
Simple test demo on: stackblitz
import { useState } from 'react';
import './App.css';
import update from 'immutability-helper';
interface AuthorState {
name: string;
}
interface BookState {
name: string;
authors: AuthorState[];
}
const bookStateInitial = [
{ name: 'Book-1', authors: [{ name: 'Author-1' }] },
{ name: 'Book-2', authors: [{ name: 'Author-1' }, { name: 'Author-2' }] },
{ name: 'Book-3', authors: [{ name: 'Author-1' }] },
{ name: 'Book-4', authors: [{ name: 'Author-1' }, { name: 'Author-2' }] },
];
function App() {
const [bookValues, setBookValues] = useState<BookState[]>(bookStateInitial);
const onClickAddAuthor = (bookIndex: number) => {
let newAuthor = { name: 'Test Author' } as AuthorState;
let authors = [...bookValues[bookIndex].authors, newAuthor];
let newBookState = update(bookValues, {
[bookIndex]: { authors: { $set: authors } },
});
setBookValues(newBookState);
};
return (
<main className="App">
<section>
{[0, 1, 2, 3].map((item) => (
<button key={item} onClick={() => onClickAddAuthor(item)}>
{`Test: add author for Book-${item + 1}`}
</button>
))}
</section>
<ul>
{bookValues.map((book) => (
<li key={book.name}>
{`name: ${book.name}, authors: ${book.authors
.map((author) => author.name)
.join(', ')}`}
</li>
))}
</ul>
</main>
);
}
export default App;

Migration to Mobx 6: functional components aren't working with decorated observables

I faced with problem while migrating from Mobx 4 to Mobx 6.
I have a functional component but after updating Mobx it stopped working. Looks like store doesn't works. Component react on changes inside observable variable by reaction feature but changes aren't re-rendering. I made everything that was provided in migration guide but component's store doesn't working.
At some reason if I change functional component to class component everything starts working. But I really can't understand the reason why such happens and can't find any explanation of such behaviour.
Case looks like example bellow. Experimental decorators are enabled and any other stuff that was provided in Migration guide as well. So what is the reason of such behaviour and how can I implement correct logic in functional component?
interface User {
name: string;
age: number;
info: {
phone: string;
email: string;
};
}
const usersData: User[] = [
{
name: "Steve",
age: 29,
info: {
phone: "+79011054333",
email: "steve1991#gmail.com",
},
},
{
name: "George",
age: 34,
info: {
phone: "+79283030322",
email: "george_the_best_777#gmail.com",
},
},
{
name: "Roger",
age: 17,
info: {
phone: "+79034451202",
email: "rodge_pirat_yohoho#gmail.com",
},
},
{
name: "Maria",
age: 22,
info: {
phone: "+79020114849",
email: "bunnyrabbit013#gmail.com",
},
},
];
const getUsers = () => {
return new Promise<User[]>((resolve) => {
setTimeout(() => {
resolve(usersData);
}, 2000);
});
};
class Store {
#observable users: User[] = [];
constructor() {
makeObservable(this);
}
async init() {
const users = await getUsers();
this.setUsers(users);
}
#action setUsers(users: User[]) {
this.users = users;
}
#action increaseUserAge(userIndex: number) {
const users = this.users.map((u, k) => {
if (k === userIndex) {
u.age += 1;
}
return u;
});
this.setUsers(users);
}
#computed get usersCount(): number {
return this.users.length;
}
}
const store = new Store();
const UserList = observer(() => {
React.useEffect(() => {
store.init();
}, []);
const addOneUser = () => {
const user = {
name: "Jesica",
age: 18,
info: {
phone: "+79886492224",
email: "jes3331#gmail.com",
},
};
store.setUsers([...store.users, user]);
};
return (
<div className="App">
<h4>Users: {store.usersCount}</h4>
{store.users.length ? (
<>
<ul>
{store.users.map((user, key) => (
<li key={key}>
Name: {user.name}, Age: {user.age}, Info:
<div>
Phone: {user.info.phone}, Email: {user.info.email}
</div>
<button onClick={() => store.increaseUserAge(key)}>
Increase Age
</button>
</li>
))}
</ul>
<button onClick={addOneUser} disabled={store.usersCount >= 5}>
Add one user
</button>
</>
) : (
<p>Fetching users...</p>
)}
</div>
);
});
function App() {
return <UserList />;
}
export default App;
I've made Codesandbox example with your code (although removed types), it works fine.
Check tsconfig.json there, maybe you forgot to enable some of the options?
Or check what versions of mobx and mobx-react are you using?
And just a small nitpick on how you use your increaseUserAge action, it can be as simple as that:
#action increaseUserAge(user) {
user.age += 1;
}
And in the jsx you just pass the whole user there:
<button onClick={() => store.increaseUserAge(user)}>
Increase Age
</button>

quick replies press function (gifted chat) react native

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);
}

In my React app I cannot get the removePlayer method to be passed to the Player component as a prop

I am able to see the name, key and Id props when I inspect the element, but not removePlayer. When I inspect the element I do the the removePlayer prop but its value is empty.
class App extends React.Component {
state = {
players: [
{name: 'player1', id: 1},
{name: 'player2', id: 2},
{name: 'player3', id: 3},
{name: 'player4', id: 4 }
]
}
removePlayer = (id) => {
this.setState( prevState => {
return {
players: prevState.players.filter( p => p.id !== id)
}
})
}
render() {
return (
<div className="scoreboard">
<Header title="Scoreboard" totalPlayers={this.state.players.length}/>
{this.state.players.map( player => {
return (
<Player
name={player.name}
id={player.id}
removePlayer={this.removePlayer}
key={String(player.id)}>
</Player>)
})}
</div>
);
}
}

Disable selection for rows with particular Row Ids in devexpress react Grid?

I am working on devexpress react grid and I am new to react. I need to disable the selection of rows based on the condition. I struggle here to disable the selection of particular rows rather than all the rows. Please help me.
https://stackblitz.com/edit/react-deg9yu?file=index.js
The above link has the demo to disable the selection if the 3 rows are selected. But in my scenario the selection checkbox should be enabled for only the rowid [0,1,5]. Other rows should be disabled for selection by default.
I found the answer to my question on below link.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
Getter,
Plugin
} from '#devexpress/dx-react-core';
import {
SelectionState,
IntegratedSelection
} from '#devexpress/dx-react-grid';
import {
Grid,
Table,
TableHeaderRow,
TableSelection
} from '#devexpress/dx-react-grid-bootstrap3';
const filters = [0,2,5];
const columns = [
{ name: 'id', title: 'ID' },
{ name: 'product', title: 'Product' },
{ name: 'owner', title: 'Owner' },
];
const rows = [
{ id: 0, product: 'DevExtreme', owner: 'DevExpress' },
{ id: 1, product: 'DevExtreme Reactive', owner: 'DevExpress' },
{ id: 2, product: 'DevExtreme Reactive 1', owner: 'DevExpress' },
{ id: 3, product: 'DevExtreme Reactive 2', owner: 'DevExpress' },
{ id: 4, product: 'DevExtreme', owner: 'DevExpress' },
{ id: 5, product: 'DevExtreme Reactive', owner: 'DevExpress' },
{ id: 6, product: 'DevExtreme Reactive 1', owner: 'DevExpress' },
{ id: 7, product: 'DevExtreme Reactive 2', owner: 'DevExpress' },
];
const rowSelectionEnabled = row => row.product === 'DevExtreme' ;
class PatchedIntegratedSelection extends React.PureComponent {
render() {
const { rowSelectionEnabled, ...restProps } = this.props;
return (
<Plugin>
<Getter
name="rows"
computed={({ rows }) => {
this.rows = rows;
return rows.filter(rowSelectionEnabled);
}}
/>
<IntegratedSelection {...restProps} />
<Getter
name="rows"
computed={() => this.rows}
/>
</Plugin>
)
}
};
class PatchedTableSelection extends React.PureComponent {
render() {
const { rowSelectionEnabled, ...restProps } = this.props;
return (
<TableSelection
cellComponent={(props) => this.props.rowSelectionEnabled(props.tableRow.row) ? (
<TableSelection.Cell {...props} />
) : (
<Table.StubCell {...props} />
)}
{...restProps}
/>
);
}
}
export default class App extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
selection: []
};
this.changeSelection = selection => this.setState({ selection });
}
render() {
const { selection } = this.state;
return (
<div>
<span>Selection: {JSON.stringify(selection)}</span>
<Grid
rows={rows}
columns={columns}
>
<SelectionState
selection={selection}
onSelectionChange={this.changeSelection}
/>
<PatchedIntegratedSelection
rowSelectionEnabled={rowSelectionEnabled}
/>
<Table />
<TableHeaderRow />
<PatchedTableSelection
showSelectAll
rowSelectionEnabled={rowSelectionEnabled}
/>
</Grid>
</div>
);
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
);
Links: https://github.com/DevExpress/devextreme-reactive/issues/1706
For anyone who is interested I achieved this by doing the following.
render() {
const {...restProps} = this.props;
return (
...
<TableSelection cellComponent={this._selectableRow}
{...restProps}
/>
...
);
}
...
_selectableRow(props)
{
const {...restProps} = props;
return props.row.type === "folder" ? <Table.StubCell/> : <TableSelection.Cell {...restProps}/>
}

Resources