0.1.0 • Published 2 years ago

react-use-controls v0.1.0

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

useControls - a React Hook to imperativelly control the state of child compoenets.

This hook is very useful for time-based tasks (animation components, etc...) when a parent component needs to control child state and do some repeatful operations in a non-declarative way.

Simple Use

import {
  useControls,
  useSetControls,
  ControlledChildProps,
} from "react-use-controls";

interface ChildControls {
  setMessage: (message: string) => void;
  message: string;
}

const Parent = () => {
  const childControls = useControls<ChildControls>();

  return (
    <>
      <button
        onClick={() =>
          childControls.do((controls) => controls.setMessage("Welcome!"))
        }
      >
        Change Child Message From Parent
      </button>
      <Child controls={childControls} />
    </>
  );
};

interface ChildProps extends ControlledChildProps {
  // Other Child Props...
}

const Child = (props: ChildProps) => {
  // Gets props.controls and give you a function to set any control you want.
  const [setControls] = useSetControls(props);

  // This is a custom state which we use to set as two controls.
  const [message, setMessage] = useState("Learn React");

  // Use an effect or more to set all child controls.
  useEffect(() => {
    setControls({ setMessage, message });
  }, [setControls, setMessage, message]);

  return <p>{message}</p>;
};

Listeners

Listeners help to detect child state changes in parent component.

This is useful when you want to use a child state value in parent and you want to sync them to be the same in two parnet and child.

import {
  useControls,
  useSetControls,
  ControlledChildProps,
} from "react-use-controls";

interface ChildControls {
  setMessage: (message: string) => void;
  message: string;
}

const Parent = () => {
  const childControls = useControls<ChildControls>({
     listen: {
        message: (value, prevValue, forceUpdate) => {
           if (value !== prevValue) {
              // This will force Parent component to update every time the message state is changed from child.
              forceUpdate();
           }
        }
     },
  });

  return (
    <>
      <button
        onClick={() =>
          childControls.do((controls) => controls.setMessage("Welcome!"))
        }
      >
        Change Child Message From Parent
      </button>

      Message In Child: <Child controls={childControls} />

      Message Used In Parent: <h2>{childControls.controls.message}</h2>
    </>
  );
};
  • You Could use listen: { message: true } instead of the method above to automatically force update on every change.
  • The Parent component above does not display message value on first render (mount phase). you can use the following effect to show the message when mounted.
React.useEffect(childControls.forceUpdate, []);