Skip to content

Commit

Permalink
fix: don't reiniting widget when callbacks change (#43)
Browse files Browse the repository at this point in the history
refactoring
fix unresolved dependencies
refactor dialog
add dummy tests
  • Loading branch information
jeetiss committed Sep 20, 2019
1 parent 070bdcc commit cac9960
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 50 deletions.
34 changes: 34 additions & 0 deletions dummy/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react'
import ReactDOM from 'react-dom'

import File from './file-select-callback'
import Panel from './default-panel'

const Example = ({ text, component: Component }) => (
<div>
<h2>{text}</h2>

<br />
<br />

<Component />

<hr />
</div>
)

const examples = [
{
text: 'rerendering on file select callback fire',
component: File
},
{
text: 'default panel example',
component: Panel
}
]

ReactDOM.render(
examples.map((props, key) => <Example key={key} {...props} />),
document.getElementById('root')
)
5 changes: 5 additions & 0 deletions dummy/default-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react'

import { Panel } from '../src'

export default () => <Panel publicKey='demopublickey' />
11 changes: 11 additions & 0 deletions dummy/file-select-callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { useReducer } from 'react'

import { Widget } from '../src'

export default () => {
const [, rerender] = useReducer(state => !state, false)

const newFn = () => rerender()

return <Widget publicKey='demopublickey' onFileSelect={newFn} />
}
14 changes: 14 additions & 0 deletions dummy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>D</title>
</head>
<body>
<div id="root"></div>

<script src="./app.js"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"module": "dist/esm/index.js",
"scripts": {
"build": "rollup -c",
"dummy": "parcel dummy/index.html",
"prepublishOnly": "npm run build",
"test:dev": "karma start karma.config.js",
"test": "karma start karma.config.js --single-run --nocache",
Expand Down Expand Up @@ -45,6 +46,7 @@
"homepage": "https://github.com/uploadcare/react-widget",
"dependencies": {
"@uploadcare/client-suspense": "^1.0.0",
"react-fast-compare": "^2.0.4",
"uploadcare-widget": "^3.7.7"
},
"peerDependencies": {
Expand Down
21 changes: 18 additions & 3 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export default [
// esm build width all locales
{
input: 'src/index.js',
external: ['react', 'uploadcare-widget', '@uploadcare/client-suspense'],
external: [
'react',
'react-fast-compare',
'uploadcare-widget',
'@uploadcare/client-suspense'
],
output: {
format: 'esm',
dir: 'dist/esm',
Expand All @@ -24,7 +29,12 @@ export default [
// cjs build width all locales
{
input: 'src/index.js',
external: ['react', 'uploadcare-widget', '@uploadcare/client-suspense'],
external: [
'react',
'react-fast-compare',
'uploadcare-widget',
'@uploadcare/client-suspense'
],
output: {
format: 'cjs',
dir: 'dist/cjs',
Expand All @@ -42,7 +52,12 @@ export default [
// esm build width en locale (30% smaller)
{
input: 'src/index.js',
external: ['react', 'uploadcare-widget/uploadcare.lang.en', '@uploadcare/client-suspense'],
external: [
'react',
'react-fast-compare',
'uploadcare-widget/uploadcare.lang.en',
'@uploadcare/client-suspense'
],
output: {
format: 'esm',
dir: 'en',
Expand Down
17 changes: 7 additions & 10 deletions src/dialog.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useRef } from 'react'
import uploadcare from 'uploadcare-widget'

import { useDestructuring, useState, useCustomTabs } from './hooks'
import { useState, useCustomTabs } from './hooks'

const containerStyles = {
height: '500px',
Expand All @@ -27,17 +27,14 @@ const Progress = ({ hidden, value }) => {
}

const useDialog = (props, uploadcare) => {
const [customTabs, options] = useDestructuring(
({ customTabs, ...options }) => [customTabs, options],
props
)

const [state, setState] = useState({
opened: true,
file: null,
progress: null
})

const { customTabs } = props

useCustomTabs(customTabs, uploadcare)

const panelContainer = useRef(null)
Expand All @@ -49,9 +46,9 @@ const useDialog = (props, uploadcare) => {
panelInstance.current = uploadcare.openPanel(
panelContainer.current,
state.file
? uploadcare.fileFrom('uploaded', state.file.uuid, options)
? uploadcare.fileFrom('uploaded', state.file.uuid, props)
: null,
options
props
)

setState({ file: null })
Expand All @@ -64,8 +61,8 @@ const useDialog = (props, uploadcare) => {
} else {
// do nothing
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uploadcare, options, setState, state.opened])
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uploadcare, props, setState, state.opened])

useEffect(
() => () => panelInstance.current && panelInstance.current.reject(),
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export * from './use-event-callback'
export * from './use-state'
export * from './use-custom-tabs'
export * from './use-validators'
export * from './use-deep-effect'
export * from './use-deep-memo'
12 changes: 12 additions & 0 deletions src/hooks/use-deep-effect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useEffect, useRef } from 'react'
import isEqual from 'react-fast-compare'

export const useDeepEffect = (effect, deps) => {
const ref = useRef(undefined)

if (!isEqual(deps, ref.current)) {
ref.current = deps
}

useEffect(effect, ref.current)
}
31 changes: 31 additions & 0 deletions src/hooks/use-deep-memo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useRef } from 'react'
import isEqual from 'react-fast-compare'

export function useDeepMemo (
factory,
deps
) {
let isValid = true

const valueRef = useRef()
// initial hook call
if (!valueRef.current) {
valueRef.current = {
deps,
result: factory()
}
// subsequent calls
} else {
isValid = !!(
deps &&
valueRef.current.deps &&
isEqual(deps, valueRef.current.deps)
)
}

const cache = isValid ? valueRef.current : { deps, result: factory() }
// must update immediately so any sync renders here don't cause an infinite loop
valueRef.current = cache

return cache.result
}
52 changes: 15 additions & 37 deletions src/uploader.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import React, {
useEffect,
useRef,
useMemo,
useCallback,
useImperativeHandle
} from 'react'
import uploadcare from 'uploadcare-widget'

import {
useDestructuring,
useEventCallback,
useCustomTabs,
useValidators
useValidators,
useDeepMemo
} from './hooks'

function camelCaseToDash (str) {
Expand All @@ -27,36 +26,15 @@ const propsToAttr = props =>
{}
)

const useWidget = (props, uploadcare) => {
const [
value,
onFileSelect,
onChange,
apiRef,
customTabs,
validators,
options
] = useDestructuring(
({
value,
onFileSelect,
onChange,
apiRef,
customTabs,
validators,
...options
}) => [
value,
onFileSelect,
onChange,
apiRef,
customTabs,
validators,
options
],
props
)

const useWidget = ({
value,
onFileSelect,
onChange,
apiRef,
customTabs,
validators,
...options
}, uploadcare) => {
const input = useRef(null)
const widget = useRef(null)

Expand All @@ -65,7 +43,7 @@ const useWidget = (props, uploadcare) => {

useCustomTabs(customTabs, uploadcare)

const attributes = useMemo(() => propsToAttr(options), [options])
const attributes = useDeepMemo(() => propsToAttr(options), [options])

useEffect(() => {
widget.current = uploadcare.Widget(input.current)
Expand All @@ -84,7 +62,7 @@ const useWidget = (props, uploadcare) => {
widget.current.onUploadComplete.remove(changeCallback)
widget.current.onChange.remove(fileSelectedCallback)
}
}, [uploadcare, attributes, changeCallback, fileSelectedCallback])
}, [changeCallback, fileSelectedCallback])

useEffect(() => {
let dialog
Expand All @@ -96,7 +74,7 @@ const useWidget = (props, uploadcare) => {
dialog && dialog.reject()
widget.current.onDialogOpen.remove(saveDialog)
}
}, [uploadcare, attributes])
}, [attributes])

useEffect(() => {
let files = []
Expand All @@ -114,7 +92,7 @@ const useWidget = (props, uploadcare) => {
files.forEach(file => file.cancel())
widget.current.onChange.remove(saveFiles)
}
}, [uploadcare, attributes])
}, [attributes])

useEffect(() => {
widget.current.value(value)
Expand Down

0 comments on commit cac9960

Please sign in to comment.