Переход между тремя состояниями со смесью реагирует на события жизненного цикла - PullRequest
0 голосов
/ 15 декабря 2018

У меня есть оверлейный компонент ReasonReact с тремя состояниями замирания.Первый виден с полной непрозрачностью, второй - почти полностью прозрачным, а третий - без отображения.

Есть ли способ использовать события жизненного цикла, чтобы избежать опроса, чтобы определить, является ли внешний isOpen пропбыло переключено?

Я попытался отправить обновление из didReceiveProps и выполнить рендеринг (но в обоих случаях возникли бесконечные циклы или сильное мерцание).

Мой текущий компонент.

type fading =
  | FadedIn
  | Intermediate
  | FadedOut;
type cycle =
  | In(fading)
  | Out(fading);

type action =
  | Cycle
  | PassTheCycle;

type state = {cycling};

let component = React.reducerComponent(__MODULE__);
let make =
    (~isOpen, ~onClick=None, children) => {
  ...component,
  didMount: ({send, onUnmount}) => {
    let interval = Js.Global.setInterval(() => PassTheCycle->send, 200);

    onUnmount(() => Js.Global.clearInterval(interval));
  },
  reducer: (action: action, state: state) => {
    let delay = (~delay=20, next) =>
      React.UpdateWithSideEffects(
        {cycling: next},
        ({send}) => Js.Global.setTimeout(() => Cycle->send, delay)->ignore,
      );

    switch (action) {
    | PassTheCycle =>
      switch (state.cycling) {
      | Out(FadedIn)
      | In(FadedOut) => React.SideEffects((({send}) => Cycle->send))
      | _ => React.NoUpdate
      }
    | Cycle =>
      switch (state.cycling) {
      | In(x) =>
        switch (x) {
        | FadedIn => React.NoUpdate
        | Intermediate => delay(~delay=200, In(FadedIn))
        | FadedOut => delay(In(Intermediate))
        }
      | Out(x) =>
        switch (x) {
        | FadedOut => React.NoUpdate
        | Intermediate => delay(~delay=200, Out(FadedOut))
        | FadedIn => delay(Out(Intermediate))
        }
      }
    };
  },
  initialState: () => {cycling: isOpen ? In(FadedIn) : Out(FadedOut)},
  willReceiveProps: ({state}) =>
    switch (isOpen, state.cycling) {
    | (false, In(x)) => {cycling: Out(x)}
    | (true, Out(x)) => {cycling: In(x)}
    | _ => state
    },
  render: ({state}) => {
    let className =
      Style.main(state.cycling);

    <div className> ...children </div>;
  },
};
...