Saturday 6 March 2021

Best practice for using scoped variables between imported functions

I am trying to create an easing function on scroll but my main function is growing rather large and I want to be able to split it up. I am creating a requestAnimationFrame function that will ease the page scroll. The big issue I am having is that the render function with the animation frame will ease the Y value and then calls the update function to update the elements. But if I split this up and import them individually I am having trouble figuring out how to pass the updated values between functions. Many other functions also rely on these updated values.

I could take an object oriented approach and create a class or a constructor function and bind this to the function but it seems like bad practice to me:

import render from './render'
import update from './update'

const controller = () => {
  this.items = [];
  this.event = {
    delta: 0,
    y: 0
  }

  this.render = render.bind(this)
  this.update = update.bind(this)
  //ect
}

I could also break it up into classes that extend each other but I would like to take a more functional approach to the situation but I am having trouble figuring out how to achieve this.

Here is a very condensed version of what I am trying to do. Codesandbox.

const controller = (container) => {
  const items = [];
  let aF = null;

  const event = {
    delta: 0,
    y: 0
  };

  const render = () => {
    const diff = event.delta - event.y;
    if (Math.abs(diff) > 0.1) {
      event.y = lerp(event.y, event.delta, 0.06);
      aF = requestAnimationFrame(render);
    } else {
      stop();
    }
    update();
  };

  const start = () => {
    if (!aF) aF = requestAnimationFrame(render);
  };

  const stop = () => {
    event.y = event.delta;
    cancelAnimationFrame(aF);
    aF = null;
  };

  const update = () => {
    const y = event.y;
    container.style.transform = `translateY(-${y}px)`;
    items.forEach((item) => {
      item.style.transform = `translate(${y}px, ${y}px)`;
    });
  };

  const addItem = (item) => items.push(item);

  const removeItem = (item) => {
    const idx = items.indexOf(item);
    if (idx > -1) items.splice(idx, 1);
  };

  const onScroll = () => {
    event.delta = window.scrollY;
    start();
  };

  // and a bunch more stuff

  window.addEventListener("scroll", onScroll);

  return {
    addItem,
    removeItem
  };
};

export default controller;

I would like to be able to split this up and create a more functional approach with pure functions where I can import the update and render functions. The problem is that these functions are reliant on the updated global variables. Everywhere I look it says that global variables are a sin but I don't see a way to avoid them here. I have tried to look at the source code for some large frameworks to get some insight on how they structure their projects but it is too much for me to take in at the moment.

Any Help would be appreciated. Thanks.



from Best practice for using scoped variables between imported functions

No comments:

Post a Comment