Remove usage of react-infinite-any-height
This module uses the index as key, this is bad, because we have a real id for identifying messages. see https://reactjs.org/docs/lists-and-keys.html
This commit is contained in:
parent
120e41ff91
commit
1a9132e5a0
|
|
@ -280,6 +280,15 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-infinite": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-infinite/-/react-infinite-0.0.33.tgz",
|
||||
"integrity": "sha512-9fVHtg811uRRqssb093qp/eIPsMroTxltv/xfOaOjdYZPndSFi7q6zxOcOVPlqVrCNjaE6JMm3z2/3LzRt0Y1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-router": {
|
||||
"version": "4.0.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.0.30.tgz",
|
||||
|
|
@ -3257,6 +3266,30 @@
|
|||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
|
||||
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
|
||||
},
|
||||
"enzyme-adapter-react-16": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz",
|
||||
"integrity": "sha512-kC8pAtU2Jk3OJ0EG8Y2813dg9Ol0TXi7UNxHzHiWs30Jo/hj7alc//G1YpKUsPP1oKl9X+Lkx+WlGJpPYA+nvw==",
|
||||
"requires": {
|
||||
"enzyme-adapter-utils": "^1.3.0",
|
||||
"lodash": "^4.17.4",
|
||||
"object.assign": "^4.0.4",
|
||||
"object.values": "^1.0.4",
|
||||
"prop-types": "^15.6.0",
|
||||
"react-reconciler": "^0.7.0",
|
||||
"react-test-renderer": "^16.0.0-0"
|
||||
}
|
||||
},
|
||||
"enzyme-adapter-utils": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.1.tgz",
|
||||
"integrity": "sha512-s3QB3xQAowaDS2sHhmEqrT13GJC4+n5bG015ZkLv60n9k5vhxxHTQRIneZmQ4hmdCZEBrvUJ89PG6fRI5OEeuQ==",
|
||||
"requires": {
|
||||
"function.prototype.name": "^1.1.0",
|
||||
"object.assign": "^4.1.0",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
|
||||
|
|
@ -4531,6 +4564,16 @@
|
|||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"function.prototype.name": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz",
|
||||
"integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
|
|
@ -4784,6 +4827,11 @@
|
|||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
|
||||
},
|
||||
"has-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
|
||||
|
|
@ -7613,6 +7661,17 @@
|
|||
"isobject": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"object.assign": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
"has-symbols": "^1.0.0",
|
||||
"object-keys": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"object.getownpropertydescriptors": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
|
|
@ -7639,6 +7698,17 @@
|
|||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"object.values": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz",
|
||||
"integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.6.1",
|
||||
"function-bind": "^1.1.0",
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"obuf": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
|
||||
|
|
@ -9554,10 +9624,11 @@
|
|||
}
|
||||
},
|
||||
"react-infinite": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/react-infinite/-/react-infinite-0.12.1.tgz",
|
||||
"integrity": "sha512-sOXsm0OsszFQQ+4Vtqt1UUqLETGOCS0keAdEQuNMmeoIHHz2iIW44cHhPLxyeAsdfJQOYanmBZjhpZFQw7bhKw==",
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-infinite/-/react-infinite-0.13.0.tgz",
|
||||
"integrity": "sha512-sISd4IYKELmOrvCq9i3FaQo4HR+Bn49ufK0eYAWQAisQ87QWJ5tqiQvEzww+JJZryZVMFvBCuiV7RUn/MfeEww==",
|
||||
"requires": {
|
||||
"enzyme-adapter-react-16": "1.1.1",
|
||||
"lodash.isarray": "3.0.4",
|
||||
"lodash.isfinite": "3.2.0",
|
||||
"object-assign": "4.0.1"
|
||||
|
|
@ -9577,8 +9648,30 @@
|
|||
"requires": {
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"react-infinite": "^0.12.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"object-assign": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.0.1.tgz",
|
||||
"integrity": "sha1-mVBEVsNZi1ytT8WcJuipuxB/4L0="
|
||||
},
|
||||
"react-infinite": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmjs.org/react-infinite/-/react-infinite-0.12.1.tgz",
|
||||
"integrity": "sha512-sOXsm0OsszFQQ+4Vtqt1UUqLETGOCS0keAdEQuNMmeoIHHz2iIW44cHhPLxyeAsdfJQOYanmBZjhpZFQw7bhKw==",
|
||||
"requires": {
|
||||
"lodash.isarray": "3.0.4",
|
||||
"lodash.isfinite": "3.2.0",
|
||||
"object-assign": "4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz",
|
||||
"integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g=="
|
||||
},
|
||||
"react-jss": {
|
||||
"version": "8.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz",
|
||||
|
|
@ -9596,6 +9689,17 @@
|
|||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-reconciler": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.7.0.tgz",
|
||||
"integrity": "sha512-50JwZ3yNyMS8fchN+jjWEJOH3Oze7UmhxeoJLn2j6f3NjpfCRbcmih83XTWmzqtar/ivd5f7tvQhvvhism2fgg==",
|
||||
"requires": {
|
||||
"fbjs": "^0.8.16",
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"react-router": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
|
||||
|
|
@ -9703,6 +9807,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-test-renderer": {
|
||||
"version": "16.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.6.0.tgz",
|
||||
"integrity": "sha512-w+Y3YT7OX1LP5KO7HCd0YR34Ol1qmISHaooPNMRYa6QzmwtcWhEGuZPr34wO8UCBIokswuhyLQUq7rjPDcEtJA==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-is": "^16.6.0",
|
||||
"scheduler": "^0.10.0"
|
||||
}
|
||||
},
|
||||
"react-timeago": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-4.1.9.tgz",
|
||||
|
|
@ -10216,6 +10331,15 @@
|
|||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.10.0.tgz",
|
||||
"integrity": "sha512-+TSTVTCBAA3h8Anei3haDc1IRwMeDmtI/y/o3iBe3Mjl2vwYF9DtPDt929HyRmV/e7au7CLu8sc4C4W0VOs29w==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"prop-types": "^15.6.2",
|
||||
"react": "^16.4.2",
|
||||
"react-dom": "^16.4.2",
|
||||
"react-infinite": "^0.13.0",
|
||||
"react-infinite-any-height": "^2.3.0",
|
||||
"react-router": "^4.3.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
"@types/puppeteer": "^1.6.3",
|
||||
"@types/react": "^16.4.11",
|
||||
"@types/react-dom": "^16.0.7",
|
||||
"@types/react-infinite": "0.0.33",
|
||||
"@types/react-router-dom": "^4.3.0",
|
||||
"@types/rimraf": "^2.0.2",
|
||||
"get-port": "^4.0.0",
|
||||
|
|
|
|||
|
|
@ -47,40 +47,51 @@ interface IProps {
|
|||
date: string;
|
||||
content: string;
|
||||
fDelete: VoidFunction;
|
||||
height: (height: number) => void;
|
||||
}
|
||||
|
||||
function Message({fDelete, classes, title, date, content, image}: IProps & Style) {
|
||||
return (
|
||||
<div className={`${classes.wrapperPadding} message`}>
|
||||
<Container style={{display: 'flex'}}>
|
||||
<div className={classes.imageWrapper}>
|
||||
<img
|
||||
src={image}
|
||||
alt="app logo"
|
||||
width="70"
|
||||
height="70"
|
||||
className={classes.image}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.messageContentWrapper}>
|
||||
<div className={classes.header}>
|
||||
<Typography className={`${classes.headerTitle} title`} variant="headline">
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="body1" className="date">
|
||||
<TimeAgo date={date} />
|
||||
</Typography>
|
||||
<IconButton onClick={fDelete} className={classes.trash}>
|
||||
<Delete className="delete" />
|
||||
</IconButton>
|
||||
class Message extends React.PureComponent<IProps & Style> {
|
||||
private node: HTMLDivElement | null;
|
||||
|
||||
public componentDidMount = () =>
|
||||
this.props.height(this.node ? this.node.getBoundingClientRect().height : 0);
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const {fDelete, classes, title, date, content, image} = this.props;
|
||||
return (
|
||||
<div className={`${classes.wrapperPadding} message`} ref={(ref) => (this.node = ref)}>
|
||||
<Container style={{display: 'flex'}}>
|
||||
<div className={classes.imageWrapper}>
|
||||
<img
|
||||
src={image}
|
||||
alt="app logo"
|
||||
width="70"
|
||||
height="70"
|
||||
className={classes.image}
|
||||
/>
|
||||
</div>
|
||||
<Typography component="p" className="content">
|
||||
{content}
|
||||
</Typography>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
<div className={classes.messageContentWrapper}>
|
||||
<div className={classes.header}>
|
||||
<Typography
|
||||
className={`${classes.headerTitle} title`}
|
||||
variant="headline">
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="body1" className="date">
|
||||
<TimeAgo date={date} />
|
||||
</Typography>
|
||||
<IconButton onClick={fDelete} className={classes.trash}>
|
||||
<Delete className="delete" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<Typography component="p" className="content">
|
||||
{content}
|
||||
</Typography>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)<IProps>(Message);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import {RouteComponentProps} from 'react-router';
|
|||
import DefaultPage from '../common/DefaultPage';
|
||||
import Message from './Message';
|
||||
import {observer} from 'mobx-react';
|
||||
// @ts-ignore
|
||||
import InfiniteAnyHeight from 'react-infinite-any-height';
|
||||
import {inject, Stores} from '../inject';
|
||||
import {observable} from 'mobx';
|
||||
import ReactInfinite from 'react-infinite';
|
||||
|
||||
interface IProps extends RouteComponentProps<{id: string}> {}
|
||||
|
||||
|
|
@ -18,6 +18,9 @@ interface IState {
|
|||
|
||||
@observer
|
||||
class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>, IState> {
|
||||
@observable
|
||||
private heights: Record<number, number> = {};
|
||||
|
||||
private static appId(props: IProps) {
|
||||
if (props === undefined) {
|
||||
return -1;
|
||||
|
|
@ -63,12 +66,14 @@ class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>,
|
|||
buttonDisabled={!hasMessages}>
|
||||
{hasMessages ? (
|
||||
<div style={{width: '100%'}} id="messages">
|
||||
<InfiniteAnyHeight
|
||||
<ReactInfinite
|
||||
key={appId}
|
||||
list={messages.map(this.renderMessage)}
|
||||
preloadAdditionalHeight={window.innerHeight * 2.5}
|
||||
useWindowAsScrollContainer
|
||||
/>
|
||||
preloadBatchSize={window.innerHeight * 3}
|
||||
elementHeight={messages.map((m) => this.heights[m.id] || 1)}>
|
||||
{messages.map(this.renderMessage)}
|
||||
</ReactInfinite>
|
||||
|
||||
{hasMore ? (
|
||||
<Grid item xs={12} style={{textAlign: 'center'}}>
|
||||
<CircularProgress size={100} />
|
||||
|
|
@ -99,10 +104,14 @@ class Messages extends Component<IProps & Stores<'messagesStore' | 'appStore'>,
|
|||
this.props.messagesStore.removeSingle(message);
|
||||
|
||||
private renderMessage = (message: IMessage) => {
|
||||
this.checkIfLoadMore();
|
||||
return (
|
||||
<Message
|
||||
key={message.id}
|
||||
height={(height) => {
|
||||
if (!this.heights[message.id]) {
|
||||
this.heights[message.id] = height;
|
||||
}
|
||||
}}
|
||||
fDelete={this.deleteMessage(message)}
|
||||
title={message.title}
|
||||
date={message.date}
|
||||
|
|
|
|||
Loading…
Reference in New Issue