package react-rules-of-hooks-ppx

  1. Overview
  2. Docs
This ppx validates the rules of React hooks in reason-react components

Install

dune-project
 Dependency

Authors

Maintainers

Sources

react-rules-of-hooks-ppx-1.4.0.tbz
sha256=75f5e3d4926ee92c9b95765e29208f1ae81c7130871a26914867d21d6829d719
sha512=13bfdf55f90e7201657188b84dcedafb1cc4b8f2f2a173fdb53cd98ddf427e43bb9e94aa105cd20576ebbd31fc680dd367835d78d06941e84a607793b2bc5086

doc/src/react_rules_of_hooks_ppx/stable.ml.html

Source file stable.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
open Ppxlib

type shape = Snd | All

let shape_of_call ~(lookup : string -> shape option)
    (expr : Parsetree.expression) : shape option =
  match Hook.call_ident expr with
  | Some txt -> (
      match Longident.name txt with
      | "useState" | "React.useState" | "useReducer" | "React.useReducer" ->
          Some Snd
      | "useRef" | "React.useRef" -> Some All
      | _ -> ( match txt with Lident name -> lookup name | _ -> None))
  | None -> None

let wrapper_shape ~lookup (vb : Parsetree.value_binding) :
    (string * shape) option =
  match vb.pvb_pat.ppat_desc with
  | Ppat_var { txt = name; _ } when Hook.is_hook_name name ->
      shape_of_call ~lookup (Bindings.body_of_fun_chain vb.pvb_expr)
      |> Option.map (fun shape -> (name, shape))
  | _ -> None

let looks_like_setter name =
  String.starts_with ~prefix:"dispatch" name
  || String.starts_with ~prefix:"set" name
     && String.length name > 3
     && ((name.[3] >= 'A' && name.[3] <= 'Z') || name.[3] = '_')

let second_tuple_element_names (pattern : Parsetree.pattern) : string list =
  match pattern.ppat_desc with
  | Ppat_tuple (_ :: pat2 :: _) -> Bindings.of_pattern pat2
  | _ -> []

let setter_bound_names (pattern : Parsetree.pattern) : string list =
  match pattern.ppat_desc with
  | Ppat_record (fields, _) ->
      fields
      |> List.concat_map
           (fun
             ((field : Longident.t Location.loc), (pat : Parsetree.pattern)) ->
             match Hook.last_component field.txt with
             | Some field_name when looks_like_setter field_name ->
                 Bindings.of_pattern pat
             | _ -> [])
  | _ -> []

let static_deps_of_binding ~lookup (vb : Parsetree.value_binding) : string list
    =
  let expr = Platform.client_view vb.pvb_expr in
  let pattern = vb.pvb_pat in
  match shape_of_call ~lookup expr with
  | Some Snd -> second_tuple_element_names pattern
  | Some All -> Bindings.of_pattern pattern
  | None ->
      if Option.is_some (Hook.hook_call expr) then
        (second_tuple_element_names pattern |> List.filter looks_like_setter)
        @ setter_bound_names pattern
      else []