Thursday, 7 October 2021

React: make a cycle-through component with both forward and backward directions using Generator

I have an array of strings to display const array = ["one", "two", "three"]; .

The UI initially shows the first item in the array i.e. "one". From there I have a button right when clicked it shows the next item or string which is two, and then three, after three it should go back to one and start from there again. I also have a left button, when clicked it shows the previous item or string, if the current string is two, the previous string is one, and then after one it starts from three and walks backward.

I am using generator to do it. Here is my attempt


function* stepGen(steps) {
  let index = 0;
  while (true) {
    const direction = yield steps[index];
    index = (index + (direction === "forward" ? 1 : -1)) % steps.length;
  }
}

const array = ["one", "two", "three"];
let gen = stepGen(array);
const getNext = () => gen.next("forward").value;
const getPrev = () => gen.next("backward").value;

export default function App() {
  const [current, setCurrent] = useState(() => getNext());
  const onRight = () => {
    const next = getNext();
    setCurrent(next);
  };
  const onLeft = () => {
    const prev = getPrev();
    setCurrent(prev);
  };

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


Here is a live demo you can play with https://codesandbox.io/s/cyclethrough1-deh8p?file=/src/App.js

Apparently the current behavior is buggy. There are multiple issues that I don't know the causes and the solutions:

  1. the UI starts with two not one. I guess it has something to do with how I initiate my state current
const [current, setCurrent] = useState(() => getNext());

I thought () => getNext() is only to get called once when the component first mounts so current should be one from the start.

And I tried to initiated the state with

const [current, setCurrent] = useState(array[0]);

It indeed starts with the first item in the array which is one but you have to click right button twice to make it go to two. Here is the live demo for this variation https://codesandbox.io/s/cyclethrough2-5gews?file=/src/App.js

  1. the left button, which should walk backward the loop doesn't work. It is broken completely. the right button works though. Not sure why.


from React: make a cycle-through component with both forward and backward directions using Generator

No comments:

Post a Comment