sc0ttj / component

A tiny library for isomorphic JavaScript components
MIT License
2 stars 1 forks source link

Feature: add a standalone `render` module #25

Closed sc0ttj closed 3 years ago

sc0ttj commented 3 years ago

Refactor the code so the DOM diffing is done by an import-able module called render (instead of domDiff).

This will have various benefits:

So, users will be able to do something like this:

import { render } from '@scottjarvis/Component'

/* define a very simple stateless component:  */
const myComponent = props => {
  render(`<h1>${props}</h1>`,  '.container');
}

/* ...or define a simple stateful component:
  * set a state into which we can interpolate values
  * define a view
  * call render() - it'll use DOM diffing to update the page
  */
const myComponent = props => {
  this.state = { ...this.state, ...props };
  this.view = `<div>...</div>`;
  render(this.view, '.container');
}

/* ...or maybe an alternative "child" component pattern:
  * extract the props we want to use 
  * define a view which uses those props
  * call render() - it'll use DOM diffing to update the page
  */
const myComponent = props => {
  const { foo, bar } = props;
  render(`<div>...</div>`, '.container');
}

Either way, you would (re)render the above components to the page with new data, like so:

myComponent({ ...someData });

...or call render() outside your components:


// simplest stateless component
const Foo = props => `<div>...</div>`;

// a stateful component 
const Foo = props => {
  this.state = { ...this.state, ...props };
  const { title, count } = this.state;
  return `<div>...</div>`;
}

// ..either of the above could be called like so:

render(Foo(someObj), '.container');

The benefits of using only render would be:

..that's only 1.6kb total for components with a state, JSX-like templating, Event handling, and DOM diffing - all with a more "React-like" API and no build tools needed.

sc0ttj commented 3 years ago

Would be nice to find some good redux or useState alternatives, that can play nice with the above patterns and be added as a module to the Component codebase:

useState-like patterns:

redux-like patterns:

Ideally, I'd also like something simpler than the above - a fromState method that simply works like so:

// a stateful component using "fromState()"

const Foo = props => {
  const { title, count } = fromState();
  return `<div>...</div>`;
}

// ...or a stateful component using initial state: "fromState([ ...initial values ])"

const Foo = props => {
  const { title, count } = fromState([ "initial text", 0 ]);
  return `<div>...</div>`;
}

And fromState() would basically do this:


// return initial state, or latest state (with props any merged in)
fromState(initial) {
  this.state = { ...this.state, ...props };
  return { ...initial, ...this.state };
}

..as far as I understand it, the above pattern should work because:

  1. the props received by the component will be known to fromState without having to pass it in
  2. this keyword in the fromState function will refer to the component in which it's called, as long as:
    • the component is an arrow function
    • fromState is not an arrow function

...I need to test that theory...

sc0ttj commented 3 years ago

DONE, #29 was merged