Hocs which resolve and inject promises.
- Used with recompose is recommended.
npm install react-inject-promise
or yarn add react-inject-promise
type ReactComponent<Props> = React.StatelessComponent<Props>|React.ComponentClass<Props>;
// A hoc(higher-order-component)
injectPromise<Props>(arg:{
values:{
[name:string]:(props:Props)=>Promise<any>
},
shouldReload:(p1:Props,p2:Props)=>boolean
})(Component:ReactComponent<Props>)
Inject the promise(s), the injected props are:
- [name]
- the user-defined name of that promise.
- [name]Loading
- Whether the promise status is "resolving"
- reload[Name]
- [Name] is capitalized [name]
- Reload the promise, which could means re-fetch data from remote api.
- set[Name]
- Manully update the resolved value
Render a function as children, the argument passed to that function is similar to 'injectPromise':
- value
- valueLoading
- reloadValue
- setValue
import * as React from "react"
import {injectPromise} from "react-inject-promise"
@injectPromise({
values:{
users:(props)=>fetch(`/users?group=${props.group}`).then(r=>r.json()),
//todos: ...
},
shouldReload=(props,nextProps)=>props.group!==nextProps.group
})
class Haha extends React.PureComponent<any,any>{
render(){
const {
users, // undefined or the resolved value
reloadUsers, // a callback to re-resolve the promise
setUsers, // set the resolved value manually
usersLoading // whether the promise is not resolved yet.
} = this.props
if(usersLoading)
return <div>loading...</div>
return <div>
{
JSON.stringify(users)
}
<button onClick={reloadUsers}>Reload Users</button>
<button onClick={()=>{
fetch(`addUser`,{
body:JSON.stringify({name:'Shane'})
}).then((newUser)=>{
setUsers(users.concat(newUser))
//or reloadUser()
})
}}>Add User</button>
</div>
}
}
import * as React from "react"
import {RenderPromise} from "react-inject-promise"
const fetchUsers = (groupId)=>fetch(`/users?group=${groupId}`).then(r=>r.json())
function Component(props){
/*
* when reloadFlag changes, the 'promise' prop will be re-called, e.g. reload data from remote API.
* it is ok to pass an inline function as 'promise' props, because RenderPromise will only use the first 'promise' prop it sees, except when reloadFlag has changed.
*/
return <RenderPromise promise={()=>fetchUsers(props.groupId)} reloadFlag={props.groupId}>
{({
value,
valueLoading,
setValue,
reloadValue
})=>{
return valueLoading?"loading...":<p>{value}</p>
}}
</RenderPromise>
}