How to use the Yield keyword in React?

Viewed 1767

I am experiencing some strange behaviours when using the yield keyword in React.

What I expect to happen is that a button and the count are rendered. Every time I press the button, the count is set to the next yield value and this is shown on the screen. I would expect the following to be logged:

Creating someProcess
0
1
2
3
4
5 
...

What is actually happening is that the count value remains at either 0 or 1. The following is actually logged:

Creating someProcess
0
1
Creating someProcess
0
Creating someProcess
0
Creating someProcess
0
1
Creating someProcess
0
...

So from what I can tell, it seems like all of the code is being re-exectuted which causes the generator function to be re-initialized.

How do I prevent this behaviour?

MyComponent.js

const MyComponent.js = () => {

    // A generator function that yields the numbers 1 through 10
    function* someProcess(someValue) {
        console.log("Creating someProcess");
        for (let i = 0; i < someValue; i += 1) {
            yield i;
        }
    }

    // Getting an instance of the generator
    const process = someProcess(10);

    // Some state for the count
    const [count, setCount] = useState(0);

    // onClick handler to get the next yield value and set the count state to that value
    const getNextYieldValue = () => {
        const nextValue = process.next().value;
        console.log(nextValue);
        setCount(nextValue);
    };

    return (
        <div>
            <button onClick={getNextYieldValue} type="button">Get Next Value</button>
            <Child count={count} />
        </div>
    );
};
1 Answers

Put your generator outside of the functional component. Every time the component renders, the function gets called which in turn recreates the generator from scratch, so the current state is lost.

// A generator function that yields the numbers 1 through 10
function* someProcess(someValue) {
  console.log("Creating someProcess");
  for (let i = 0; i < someValue; i += 1) {
    yield i;
  }
}

// Getting an instance of the generator
const process = someProcess(10);

MyComponent.js = () => {
    // Some state for the count
    const [count, setCount] = useState(0);

    // onClick handler to get the next yield value and set the count state to that value
    const getNextYieldValue = () => {
        const nextValue = process.next().value;
        console.log(nextValue);
        setCount(nextValue);
    };

    return (
        <div>
            <button onClick={getNextYieldValue} type="button">Get Next Value</button>
            <Child count={count} />
        </div>
    );
};
Related