From d2098c3d0c10219a969708e9c5a192a799f47bdf Mon Sep 17 00:00:00 2001 From: Maxime Quandalle Date: Tue, 8 Oct 2019 17:34:45 +0200 Subject: [PATCH] Refacto de du composant Distribution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⬆ MAJ de react-spring vers version 8 Quelques changements d'API. Par ailleurs la version 8 exporte deux modules l'un avec les "render-props" et l'autres avec les "hooks" 🔥 Suppression de @researchgate/react-intersection-observer Remplacement par un custom hook --- package.json | 3 +- source/components/Distribution.js | 154 ++++++++---------- source/components/ui/animate.js | 20 +-- .../utils/useDisplayOnIntersecting.js | 31 ++++ yarn.lock | 22 +-- 5 files changed, 118 insertions(+), 112 deletions(-) create mode 100644 source/components/utils/useDisplayOnIntersecting.js diff --git a/package.json b/package.json index 3c2f50768..215c126b4 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "dependencies": { "@babel/polyfill": "^7.4.0", "@babel/runtime": "^7.3.4", - "@researchgate/react-intersection-observer": "^0.7.3", "classnames": "^2.2.5", "color-convert": "^1.9.2", "core-js": "^3.2.1", @@ -51,7 +50,7 @@ "react-router-dom": "^5.1.1", "react-select": "^1.2.1", "react-select-fast-filter-options": "^0.2.3", - "react-spring": "^5.8.0", + "react-spring": "=8.0.27", "react-syntax-highlighter": "^10.1.1", "react-transition-group": "^2.2.1", "react-virtualized": "^9.20.0", diff --git a/source/components/Distribution.js b/source/components/Distribution.js index b62346c4e..da764350c 100644 --- a/source/components/Distribution.js +++ b/source/components/Distribution.js @@ -1,114 +1,98 @@ -/* @flow */ - -import Observer from '@researchgate/react-intersection-observer' -import withColours from 'Components/utils/withColours' +import { ThemeColoursContext } from 'Components/utils/withColours' import Value from 'Components/Value' import { findRuleByDottedName } from 'Engine/rules' -import React, { useState } from 'react' +import React, { useContext } from 'react' import emoji from 'react-easy-emoji' -import { connect } from 'react-redux' -import { config, Spring } from 'react-spring' -import { compose } from 'redux' +import { useSelector } from 'react-redux' +import { config, animated, useSpring } from 'react-spring' import { flatRulesSelector } from 'Selectors/analyseSelectors' import répartitionSelector from 'Selectors/repartitionSelectors' import { isIE } from '../utils' import './Distribution.css' import './PaySlip' import RuleLink from './RuleLink' -import type { ThemeColours } from 'Components/utils/withColours' -import type { Répartition } from 'Types/ResultViewTypes.js' +import useDisplayOnIntersecting from 'Components/utils/useDisplayOnIntersecting' -type Props = ?Répartition & { - colours: ThemeColours -} - -const ANIMATION_SPRING = config.gentle -function Distribution({ - colours: { colour }, - rules, - // $FlowFixMe - ...distribution -}: Props) { - const [branchesInViewport, setBranchesInViewport] = useState([]) - - const handleBrancheInViewport = branche => (event, unobserve) => { - if (!event.isIntersecting) { - return - } - unobserve() - setBranchesInViewport(branchesInViewport => [ - branche, - ...branchesInViewport - ]) - } +export default function Distribution() { + const distribution = useSelector(répartitionSelector) if (!Object.values(distribution).length) { return null } - const { répartition, cotisationMaximum, total } = distribution return ( <>
- {répartition.map( - ([brancheDottedName, { partPatronale, partSalariale }]) => { - const branche = findRuleByDottedName(rules, brancheDottedName), - brancheInViewport = - branchesInViewport.indexOf(brancheDottedName) !== -1 - const montant = brancheInViewport - ? partPatronale + partSalariale - : 0 - - return ( - - - {styles => ( -
- -
-

- - - -
- {branche.summary} -

- -
-
- )} -
-
- ) - } + {distribution.répartition.map( + ([brancheDottedName, { partPatronale, partSalariale }]) => ( + + ) )}
) } -export default compose( - withColours, - connect(state => ({ - ...répartitionSelector(state), - rules: flatRulesSelector(state) - })) -)(Distribution) + +const ANIMATION_SPRING = config.gentle +function DistributionBranch({ + brancheDottedName, + partPatronale, + partSalariale, + distribution +}) { + const rules = useSelector(flatRulesSelector) + const [intersectionRef, brancheInViewport] = useDisplayOnIntersecting({ + threshold: 0.5 + }) + const colours = useContext(ThemeColoursContext) + const branche = findRuleByDottedName(rules, brancheDottedName) + const montant = brancheInViewport ? partPatronale + partSalariale : 0 + const styles = useSpring({ + config: ANIMATION_SPRING, + to: { + flex: montant / distribution.cotisationMaximum, + opacity: montant ? 1 : 0 + } + }) + + return ( + + +
+

+ + + +
+ {branche.summary} +

+ +
+
+ ) +} let ChartItemBar = ({ styles, colour, montant }) => (
-
+ to={{ opacity: 1, y: 0 }} + items={children}> {/* eslint-disable-next-line react/display-name */} - {React.Children.map(children, (item, i) => ({ y, ...style }) => ( + {item => ({ y, ...style }) => ( y !== 0 ? `translate3d(0, ${y}px,0)` : 'none' @@ -46,7 +46,7 @@ export const fromBottom = ({ }}> {item} - ))} + )} ) export const fromTop = ({ @@ -62,11 +62,11 @@ export const fromTop = ({ config={config} leave={{ opacity: 0, y: 20 }} from={{ opacity: 0, y: -20 }} - to={{ opacity: 1, y: 0 }}> + to={{ opacity: 1, y: 0 }} + items={children}> {/* eslint-disable-next-line react/display-name */} - {React.Children.map(children, (item, i) => ({ y, ...style }) => ( + {item => ({ y, ...style }) => ( y ? `translate3d(0, ${y}px,0)` : 'none' @@ -76,7 +76,7 @@ export const fromTop = ({ }}> {item} - ))} + )} ) diff --git a/source/components/utils/useDisplayOnIntersecting.js b/source/components/utils/useDisplayOnIntersecting.js new file mode 100644 index 000000000..58562689b --- /dev/null +++ b/source/components/utils/useDisplayOnIntersecting.js @@ -0,0 +1,31 @@ +import { useEffect, useRef, useState } from 'react' + +export default function({ root = null, rootMargin, threshold = 0 }) { + const ref = useRef() + const [wasOnScreen, setWasOnScreen] = useState(false) + + useEffect(() => { + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + setWasOnScreen(entry.isIntersecting) + observer.unobserve(ref.current) + } + }, + { + root, + rootMargin, + threshold + } + ) + const node = ref.current + if (ref.current) { + observer.observe(node) + } + return () => { + observer.unobserve(node) + } + }, [root, rootMargin, threshold]) // Empty array ensures that effect is only run on mount and unmount + + return [ref, wasOnScreen] +} diff --git a/yarn.lock b/yarn.lock index e5a1f4981..632bda520 100644 --- a/yarn.lock +++ b/yarn.lock @@ -744,7 +744,7 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12" integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ== @@ -948,15 +948,6 @@ promise-limit "^2.5.0" puppeteer "^1.7.0" -"@researchgate/react-intersection-observer@^0.7.3": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@researchgate/react-intersection-observer/-/react-intersection-observer-0.7.4.tgz#9360274611beebd801e3c068294ddf2ab0d4b163" - integrity sha512-4F291saKAP9I25Qe1ePflvm1DLLA43GlBIZfpMFYWofph7CAm+19nT8xwkQqSszg4PwZa5BpkaI4tAEJHtlj3w== - dependencies: - invariant "^2.2.2" - prop-types "^15.6.0" - warning "^3.0.0" - "@sindresorhus/is@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" @@ -8175,12 +8166,13 @@ react-side-effect@^1.1.0: exenv "^1.2.1" shallowequal "^1.0.1" -react-spring@^5.8.0: - version "5.9.2" - resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-5.9.2.tgz#4c4e048ffce24755eaa60acd2f3fe4a3d686ef16" - integrity sha512-ZDCBm4OaYuuSER3k7EELn9AKGs98HI23qMRL93zUUw6AlyBmqoU+eAfouGRx47gVkZkH+hArJXBHf4UGYpH9Og== +react-spring@=8.0.27: + version "8.0.27" + resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.27.tgz#97d4dee677f41e0b2adcb696f3839680a3aa356a" + integrity sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g== dependencies: - "@babel/runtime" "^7.0.0" + "@babel/runtime" "^7.3.1" + prop-types "^15.5.8" react-syntax-highlighter@^10.1.1: version "10.3.5"