Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine Form-Field communication #324

Open
6 tasks
kettanaito opened this issue Nov 6, 2018 · 2 comments
Open
6 tasks

Refine Form-Field communication #324

kettanaito opened this issue Nov 6, 2018 · 2 comments
Labels
breaking-change Change leading to major release. CRITICAL enhancement Enhances existing functionality. help wanted Extra attention is needed refactoring scope:architecture Changes affect architecture.
Milestone

Comments

@kettanaito
Copy link
Owner

kettanaito commented Nov 6, 2018

What

I suggest to refine the existing Form-Field communication.

Why

Current implementation relies on dispatching side-effects during Field's componentWillReceiveProps, which is not recommended. This, eventually, results into unstable tests.

How

  • Consider RxJs patterns

Roadmap

  • Buffer fieldUnregister event unregister multiple fields within a single state update
  • Buffer fieldChange event to handle concurrent field changes as a single state update
  • Consider new React Context API to propagate context to fields (Update to new React context API #232)
  • Refine and minimize the data passed via context
  • Handle controlled fields interactions
  • Handle uncontrolled fields interactions
@kettanaito kettanaito added enhancement Enhances existing functionality. scope:architecture Changes affect architecture. breaking-change Change leading to major release. refactoring labels Nov 6, 2018
@kettanaito kettanaito added this to the 2.0 milestone Nov 6, 2018
@kettanaito kettanaito added the help wanted Extra attention is needed label Nov 6, 2018
@kettanaito
Copy link
Owner Author

kettanaito commented Dec 3, 2018

Render from context instead of an internal variable

// createField.js
constructor() {
  this.initialFieldState = this.register()
}

// create a shorthand that always resolves to
// a) relevant field state reference in the form's state
// b) initial field state, in case form state is not yet updated
get fieldState = () => {
  return R.pathOr(this.fieldPath, this.initialFieldState, this.context.fields)
}

render() {
  // reference field state consistently, it's derived from the context
  const { fieldState } = this
  const fieldProps = deriveFrom(fieldState)

  return (...)
}

Communicate field component update

// createField.js
componentDidUpdate(nextProps) {
  // always emit field update event, no other logic here
  this.eventEmitter.emit('fieldDidUpdate', { prevProps: this.props, nextProps })
}
// Form.jsx
constructor() {
  fromEvent(this.eventEmitter, 'fieldDidUpdate').subscribe(this.fieldDidUpdate)
}

// listen to any field update and decide upon the necessity of the state update
// @todo propagate the "fieldState" reference to know which field has updated
fieldDidUpdate = ({ prevProps, nextProps, fieldState }) => {
  const { valuePropName } = fieldState

  // this should fallback to "false" when the field update is caused by fields state update
  // which cause "context" update, and field re-render, that triggers "cDU".
  if (!R.equals(prevProps[valuePropName], nextProps[valuePropName]) {
    this.updateFieldsWith(nextFieldState)
  }
}

@kettanaito
Copy link
Owner Author

The areas covered by the chunked state updates:

  • change
  • focus
  • blur
  • reset
  • clear
  • setValues
  • setErrors
  • serialize

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change Change leading to major release. CRITICAL enhancement Enhances existing functionality. help wanted Extra attention is needed refactoring scope:architecture Changes affect architecture.
Projects
None yet
Development

No branches or pull requests

1 participant