Przeglądaj źródła

Merge pull request #8103 from overleaf/ae-state-hooks-types

Add types to scope state hooks

GitOrigin-RevId: 61f903120b84a1770b1047953deb3a76ccfc50f0
Alf Eaton 4 lat temu
rodzic
commit
309742c37b

+ 5 - 3
services/web/frontend/js/shared/hooks/use-persisted-state.ts

@@ -5,6 +5,7 @@ import {
   SetStateAction,
   Dispatch,
 } from 'react'
+import _ from 'lodash'
 import localStorage from '../../infrastructure/local-storage'
 
 function usePersistedState<T>(
@@ -17,10 +18,11 @@ function usePersistedState<T>(
   })
 
   const updateFunction = useCallback(
-    newValue => {
+    (newValue: SetStateAction<T>) => {
       setValue(value => {
-        const actualNewValue =
-          typeof newValue === 'function' ? newValue(value) : newValue
+        const actualNewValue = _.isFunction(newValue)
+          ? newValue(value)
+          : newValue
 
         if (actualNewValue === defaultValue) {
           localStorage.removeItem(key)

+ 13 - 12
services/web/frontend/js/shared/hooks/use-scope-value-setter-only.js → services/web/frontend/js/shared/hooks/use-scope-value-setter-only.ts

@@ -1,5 +1,9 @@
-import PropTypes from 'prop-types'
-import { useCallback, useState } from 'react'
+import {
+  type Dispatch,
+  type SetStateAction,
+  useCallback,
+  useState,
+} from 'react'
 import { useIdeContext } from '../context/ide-context'
 import _ from 'lodash'
 
@@ -10,20 +14,17 @@ import _ from 'lodash'
  *
  * The interface is compatible with React.useState(), including
  * the option of passing a function to the setter.
- *
- * @param {string} path - dot '.' path of a property in the Angular scope.
- * @param {any} [defaultValue]
- * @returns {[any, function]} - value and setter function tuple.
  */
-export default function useScopeValueSetterOnly(path, defaultValue) {
-  const { $scope } = useIdeContext({
-    $scope: PropTypes.object.isRequired,
-  })
+export default function useScopeValueSetterOnly<T = any>(
+  path: string, // dot '.' path of a property in the Angular scope.
+  defaultValue?: T
+): [T, Dispatch<SetStateAction<T>>] {
+  const { $scope } = useIdeContext()
 
-  const [value, setValue] = useState(defaultValue)
+  const [value, setValue] = useState<T>(defaultValue)
 
   const scopeSetter = useCallback(
-    newValue => {
+    (newValue: SetStateAction<T>) => {
       setValue(val => {
         const actualNewValue = _.isFunction(newValue) ? newValue(val) : newValue
         $scope.$applyAsync(() => _.set($scope, path, actualNewValue))

+ 14 - 12
services/web/frontend/js/shared/hooks/use-scope-value.js → services/web/frontend/js/shared/hooks/use-scope-value.ts

@@ -1,5 +1,10 @@
-import { useCallback, useEffect, useState } from 'react'
-import PropTypes from 'prop-types'
+import {
+  type Dispatch,
+  type SetStateAction,
+  useCallback,
+  useEffect,
+  useState,
+} from 'react'
 import _ from 'lodash'
 import { useIdeContext } from '../context/ide-context'
 
@@ -7,17 +12,14 @@ import { useIdeContext } from '../context/ide-context'
  * Binds a property in an Angular scope making it accessible in a React
  * component. The interface is compatible with React.useState(), including
  * the option of passing a function to the setter.
- *
- * @param {string} path - dot '.' path of a property in the Angular scope.
- * @param {boolean} deep
- * @returns {[any, function]} - Binded value and setter function tuple.
  */
-export default function useScopeValue(path, deep = false) {
-  const { $scope } = useIdeContext({
-    $scope: PropTypes.object.isRequired,
-  })
+export default function useScopeValue<T = any>(
+  path: string, // dot '.' path of a property in the Angular scope
+  deep = false
+): [T, Dispatch<SetStateAction<T>>] {
+  const { $scope } = useIdeContext()
 
-  const [value, setValue] = useState(() => _.get($scope, path))
+  const [value, setValue] = useState<T>(() => _.get($scope, path))
 
   useEffect(() => {
     return $scope.$watch(
@@ -34,7 +36,7 @@ export default function useScopeValue(path, deep = false) {
   }, [path, $scope, deep])
 
   const scopeSetter = useCallback(
-    newValue => {
+    (newValue: SetStateAction<T>) => {
       setValue(val => {
         const actualNewValue = _.isFunction(newValue) ? newValue(val) : newValue
         $scope.$applyAsync(() => _.set($scope, path, actualNewValue))