Home > Enterprise >  React: questions about manipulating React states with framework-agnostic util functions
React: questions about manipulating React states with framework-agnostic util functions

Time:10-07

I am writing a util function called cycleThrough that uses a generator to cycle through an iterable and can either go forward or backward. (I am really bad at naming please feel free to suggest a better name)

function cycleThrough(iterable, { startIndex = 0 } = {}) {
  let index = startIndex;
  const mod = (n, r) => ((n % r)   r) % r;
  const iterator = (function* () {
    while (true) {
      const dir = yield iterable[index];
      index = mod(index   dir, iterable.length);
    }
  })();

  return {
    getPrev: () => iterator.next(-1).value,
    getNext: () => iterator.next(1).value
  };
}

So if we pass const array = ["1", "2", "3"]; as the iterable , then getNext would iterate through the array one by one and go back to the beginning i.e. 1 -> 2 -> 3 -> 1 -> 2, vice versa for getPrev - 1 -> 3 -> 2 -> 1

In a React component I want to display the current item of the array, and one button to go to the next item and another button to go back to the previous item. This is my implementation.


function cycleThrough(iterable, { startIndex = 0 } = {}) {
  let index = startIndex;
  const mod = (n, r) => ((n % r)   r) % r;
  const iterator = (function* () {
    while (true) {
      const dir = yield iterable[index];
      index = mod(index   dir, iterable.length);
    }
  })();

  return {
    getPrev: () => iterator.next(-1).value,
    getNext: () => iterator.next(1).value
  };
}

const array = ["1", "2", "3"];
const { getNext, getPrev } = cycleThrough(array, { startIndex: 1 });

export default function App() {
  const [current, setCurrent] = useState(array[0]);

  const onLeft = () => {
    const prev = getPrev();
    setCurrent(prev);
  };

  const onRight = () => {
    const next = getNext();
    setCurrent(next);
  };

  return (
    <div className="App">
      <h1>{current}</h1>
      <button onClick={onLeft}>left</button>
      <button onClick={onRight}>right</button>
    </div>
  );
}

It works ok and here is the live demo you can play with Edit react-questions-about-manipulating-react-states-with-framework-agnostic-util-fu

CodePudding user response:

As Drew mentioned, you can use useMemo to fix this. But I suggested another method. Using hooks. This is simpler and more appropriate to React.

const useCycleThrough = (iterable, startIndex) => {
  const [index, setIndex] = useState(startIndex);

  const goPrev = () => {
    setIndex((old) => (iterable.length   old - 1) % iterable.length);
  };

  const goNext = () => {
    setIndex((old) => (iterable.length   old   1) % iterable.length);
  };

  return [iterable[index], goPrev, goNext];
};

CodeSandbox

  • Related