Skip to content
This repository was archived by the owner on Nov 27, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 105 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
# react-pullrefresh

Pull to reflesh material design component.
Pull to reflesh material design component.<br>
react-native is supported.

![](/2017_03_06_13_09_14.gif?raw=true)

#### Demo
## Demo

[https://yusukeshibata.github.io/react-pullrefresh/](https://yusukeshibata.github.io/react-pullrefresh/)
<https://yusukeshibata.github.io/react-pullrefresh/>

## Install

#### Install

```sh
npm install react-pullrefresh
```
```sh
npm install react-pullrefresh
```

#### Usage
## Usage

```javascript
import PullRefresh from 'react-pullrefresh'
```javascript
import PullRefresh from 'react-pullrefresh'

class App extends Component {
// onRefresh function canbe async/sync
Expand All @@ -44,22 +43,106 @@ react-native is supported.

export default App
```

### HOC (High Order Component)

```javascript
import PullRefresh, { Indicator } from 'react-pullrefresh'

const PortalIncidator = PortalHoc(Indicator)
// control props namespace for List component.
// add extra onRequestMore and pullFreshProps prop that not conflict with List Component.
function PullRefreshHoc(AnotherComponent) {
return class _PullRefreshHoc extends React.Component {
handleRefresh = () => {
if (typeof this.props.onRequestMore === 'function') {
const reason = "pullRefresh"
return this.props.onRequestMore(reason)
}
}

render() {
// use pullFreshProps props namespace.
const { pullFreshProps, onRequestMore, ...otherProps } = this.props;
const defautWraperComponent = React.Fragment
const _pullFreshProps = Object.assign(
// change default wraperComponent to React.Fragment.
{
wraperComponent: defautWraperComponent
IndicatorComponent: PortalIncidator
},
pullFreshProps,
// pullFreshProps should never override AnotherComponent.
{
component: AnotherComponent,
onRefresh: this.handleRefresh
})
return (
<PullRefresh
// if pass pullFreshProps PullRefresh will ignore other props
pullFreshProps={_pullFreshProps}
// otherProps will pass to AnotherComponent
{...otherProps}
// if other HOCs(like infinite load) take onRequestMore prop(you can check by Component.propTypes)
// then pass it.
// else ignore it
onRequestMore={onRequestMore}
/>
)
}
}
}


// EnhancedList get extra two prop(onRequestMore, pullFreshProps)
// for pull refresh feature.
export const EnhancedList = PullRefreshHoc(List)

// or more enhance
const enhance = compose(FlipMoveHoc, InfiniteLoadHoc, ...OtherFeatureHocs)
export const MulitiEnhancedList = enhance(EnhancedList)


const handleRequestMore = async (reason) => {
if (reason === 'pullRefresh') {
await fetchData({page: 1})
} else if (reason === 'bottomInfiniteLoad') {
await fetchData({page: getNextPage()})
}
}

// List's prop disabled and component not conflict with pullRefresh props.
const pullRefreshProps = {
color: "#ff0000",
disabled: false,
zIndex: 20
}
const list = (
<EnhancedList
disabled={true}
component="ul"
onRequestMore={handleRequestMore}
pullRefreshProps={pullRefreshProps}>
{listItems}
</EnhancedList>
)
```

#### Behaviour difference between v1/v2

TODO:

#### Props

##### render
##### render

TODO:


##### color
##### color

default: `#787878`

##### bgColor
##### bgColor

default: `#ffffff`

Expand Down Expand Up @@ -91,13 +174,13 @@ default: `undefined`

#### Removed props

* size
* offset
* max
* waitingComponent
* pullingComponent
* pulledComponent
* supportDesktop
- size
- offset
- max
- waitingComponent
- pullingComponent
- pulledComponent
- supportDesktop

#### License

Expand Down
46 changes: 23 additions & 23 deletions src/component/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const Component = styled.div`
border-radius: 20px;
width: 40px;
height: 40px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12),
0 3px 1px -2px rgba(0, 0, 0, 0.2);
`

const RotatingSvg = styled.svg`
Expand All @@ -44,9 +45,8 @@ const DashedCircle = styled.circle`
animation: ${dashed} 1.4s ease-in-out infinite;
`

export default (props, state) => {
const { max, yRefreshing, y, phase } = state
const { zIndex, color, bgColor } = props
export default props => {
const { zIndex, color, bgColor, max, yRefreshing, y, phase } = props
const p = Math.atan(y / max)
const pMax = Math.atan(yRefreshing / max)
const r = Math.PI * 10 * 2
Expand All @@ -55,47 +55,47 @@ export default (props, state) => {
const refreshed = phase === 'refreshed'
return (
<Component
key='pull'
key="pull"
zIndex={zIndex}
style={{
top: Math.max(refreshed ? Math.atan(1) : p, 0) * max - 10,
transform: `translate(-50%, -100%) scale(${refreshed ? p : 1},${refreshed ? p : 1})`,
transform: `translate(-50%, -100%) scale(${refreshed ? p : 1},${
refreshed ? p : 1
})`,
backgroundColor: bgColor
}}
>
<Svg
style={{
transform:`rotate(${yRefreshing}deg)`
transform: `rotate(${yRefreshing}deg)`
}}
width={40}
height={40}
viewBox='0 0 40 40'
viewBox="0 0 40 40"
>
<Circle
style={{ opacity:pMax }}
style={{ opacity: pMax }}
stroke={color}
strokeWidth={2.5}
strokeDasharray={[r * pMax * 0.6, r * (1 - pMax * 0.6)]}
strokeDashoffset={-r * (1 - pMax * 0.6)}
fill='none'
fill="none"
cx={20}
cy={20}
r={8.5}
/>
{ phase !== 'refreshing' &&
<path
style={{
opacity: pMax,
transformOrigin: '50% 0%',
transform: `scale(${Math.min(pMax, 1)}, ${Math.min(pMax, 1)})`
}}
fill={color}
d='M23.5,19l5,5l5-5H23.5z'
/>
}
{phase !== 'refreshing' && (
<path
style={{
opacity: pMax,
transformOrigin: '50% 0%',
transform: `scale(${Math.min(pMax, 1)}, ${Math.min(pMax, 1)})`
}}
fill={color}
d="M23.5,19l5,5l5-5H23.5z"
/>
)}
</Svg>
</Component>
)
}


Loading