Reputation: 73908
I have the following react component (it works), but I am using a cb for setState.
I would like to know how to refactory the code removing the cb from the code:
this.setState({ viewer: null, document: null }, () => this.getViewer(type, item))
export class DocumentComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
document: null,
viewer: null,
}
}
getViewer(type, item) {
let node = null
switch (type) {
case 'image':
node = (
<Imager url={item.src} />
)
this.setState({ viewer: node, document: item })
break
default:
this.setState({ viewer: null, document: null })
return null
}
}
openViewer(type, item) {
this.setState({ viewer: null, document: null }, () => this.getViewer(type, item))
}
handlerOnClick(item: Object) {
this.openViewer('image', item)
}
render() {
const { tileData, classes } = this.props
return (
<div className={classes.root}>
<Thumbnailss tileData={tileData} handlerOnClick={item => this.handlerOnClick(item)} />
{this.state.viewer}
</div>
)
}
}
export default DocumentComponent
Upvotes: 1
Views: 553
Reputation: 93173
I assume/ you assume you are using babel and ES7. If so, you can use async
instead.
using cb
openViewer(type, item) {
this.setState({ viewer: null, document: null }, () => this.getViewer(type, item))
}
using async-await
async openViewer(type, item) {
await this.setState({ viewer: null, document: null });
this.getViewer(type, item)
}
We were tested this approach and it works fine in our environments.
using promises
Or if you are comfortable with promises .
export class DocumentComponent extends React.Component {
// override and extend setState
setState(state) {
return new Promise((resolve) => {
super.setState(state, resolve);
});
}
//...
//...
openViewer(type, item) {
this.setState({ viewer: null, document: null })
.then(() => this.getViewer(type, item))
}
}
Upvotes: 3
Reputation: 104369
Why not this way?
Instead of storing UI elements in state, store the data that you want to use, like src and type in your case. Call getViewer
method from render it will return the proper ui items. By this way you don't need to worry about setState callback, whenever you update the value of type and src, react will update the ui automatically.
export class DocumentComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
src: '',
type: '',
}
}
getViewer() {
switch (this.state.type) {
case 'image': return <Imager url={this.state.src} />
default: return null
}
}
handlerOnClick(item: Object) {
this.setState({
type: 'image',
src: item.src
})
}
render() {
const { tileData, classes } = this.props
return (
<div className={classes.root}>
<Thumbnailss tileData={tileData} handlerOnClick={item => this.handlerOnClick(item)} />
{this.getViewer()}
</div>
)
}
}
export default DocumentComponent
Upvotes: 3
Reputation: 31
Try this:
setViewer(type, item) {
switch (type) {
case 'image':
const node = (
<Imager url={item.src} />
);
this.setState({ viewer: node, document: item });
break;
default:
this.setState({ viewer: null, document: null });
}
}
openViewer(type, item) {
this.setViewer(type, item);
}
Upvotes: 0