scope-value-hook.js 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. import { useCallback, useEffect, useState } from 'react'
  2. import _ from 'lodash'
  3. /**
  4. * Binds a property in an Angular scope making it accessible in a React
  5. * component. The interface is compatible with React.useState(), including
  6. * the option of passing a function to the setter.
  7. *
  8. * @param {string} path - dot '.' path of a property in `sourceScope`.
  9. * @param {object} $scope - Angular $scope containing the value to bind.
  10. * @param {boolean} deep
  11. * @returns {[any, function]} - Binded value and setter function tuple.
  12. */
  13. export default function useScopeValue(path, $scope, deep = false) {
  14. const [value, setValue] = useState(() => _.get($scope, path))
  15. useEffect(() => {
  16. return $scope.$watch(
  17. path,
  18. newValue => {
  19. setValue(deep ? _.cloneDeep(newValue) : newValue)
  20. },
  21. deep
  22. )
  23. }, [path, $scope, deep])
  24. const scopeSetter = useCallback(
  25. newValue => {
  26. setValue(val => {
  27. const actualNewValue = _.isFunction(newValue) ? newValue(val) : newValue
  28. $scope.$applyAsync(() => _.set($scope, path, actualNewValue))
  29. return actualNewValue
  30. })
  31. },
  32. [path, $scope]
  33. )
  34. return [value, scopeSetter]
  35. }