Skip to content

adds optional options argument; adds deepmerge to options#4

Closed
apeltz wants to merge 4 commits into
synacor:masterfrom
apeltz:deepMerge
Closed

adds optional options argument; adds deepmerge to options#4
apeltz wants to merge 4 commits into
synacor:masterfrom
apeltz:deepMerge

Conversation

@apeltz

@apeltz apeltz commented Aug 22, 2017

Copy link
Copy Markdown

No description provided.

@apeltz

apeltz commented Sep 5, 2017

Copy link
Copy Markdown
Author

@developit @pl12133 this may be a solution looking for a problem, but addresses conflicts in which a non-primative prop is passed to a consuming component by multiple wrappers, and the consuming component would like the resulting prop to be a merged version

@pl12133

pl12133 commented Sep 6, 2017

Copy link
Copy Markdown

@apeltz Totally forgot about this, I can review tomorrow. This is definitely an issue which creates very unexpected behavior so I might even prefer skipping options and doing a deep merge by default.

@pl12133

pl12133 commented Sep 7, 2017

Copy link
Copy Markdown

To summarize the problem here:

You create a withConfig enhancer using defaults, with nested objects:

const defaultConfig = {
  fooConfig: {
    defaultKey: 'defaultValue'
  }
};

const withConfig = preconf(null, defaultConfig);

So far so good, your Component gets an Object from @withConfig('fooConfig') shaped as { defaultKey: 'defaultValue' }.

The problem surfaces when a component somewhere else in the tree adds additional keys to the nested object:

const overrideConfig = {
  fooConfig: {
    overrideKey: 'overrideValue'
  }
}
const withConfig= preconf(null, overrideConfig);

Now, you may be expecting that @withConfig('fooConfig') will return an Object shaped like this:

{
  overrideKey: 'overrideValue',
  defaultKey: 'defaultValue'
}

However by adding fooConfig to context, the value of fooConfig is now pulled from context.config instead of defaults. The effectively means that the overrideConfig has replaced instead of merged with the default values from defaultConfig. Therefore @withConfig('fooConfig') will return an Object with one key, { overrideKey: 'overrideValue' }.

As far as default behavior goes, it's extremely confusing. 👻 Rather than adding an option to disable it, I think we should probably move forward with a merge being the only behavior.

@apeltz

apeltz commented Jan 30, 2018

Copy link
Copy Markdown
Author

I forgot about this until now. Is this something we still think is useful? @pl12133 @Aneurysm9

@pl12133

pl12133 commented Jan 30, 2018

Copy link
Copy Markdown

Yup, we should definitely get this merged. I'm thinking mostly we just need to test it on some existing components and see if it breaks anything.

@developit

Copy link
Copy Markdown
Contributor

Agreed with @pl12133 - the current behaviour was never meant to handle returning merged objects, only leaf values.

@apeltz

apeltz commented Jan 31, 2018

Copy link
Copy Markdown
Author

It should be merged as a major semver update since it's breaking anyway. Then we can selectively update components to validate that nothing is broken or patch what is?

@pl12133

pl12133 commented Feb 1, 2018

Copy link
Copy Markdown

Interestingly @billneff79 might have found a way to solve this at the <Provider> level: synacor/preact-context-provider#3.

@pl12133 pl12133 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It runs, let's ship it as a beta! Thanks for working on this @apeltz

@apeltz

apeltz commented Feb 8, 2018

Copy link
Copy Markdown
Author

@pl12133 some updates in this latest commit:

  • made the naming more similar to @billneff79 's addition to preact-context-provider
  • added the ability to accept arrays of keys to selectively deep-merge
  • added a option to toggle the merging precedence between the node config and config from contex, defaulted to context overriding default/node config

@apeltz

apeltz commented Mar 3, 2018

Copy link
Copy Markdown
Author

@pl12133 I added some test cases that are more readable and also fixed an error in a docblock example use case I had.

@billneff79 's synacor/preact-context-provider#3 does provide a path to accomplish the same thing that the functionality here does, but this addition will allow us to continue to use preconf as we currently are while without an additional provider wrapper.

@billneff79

Copy link
Copy Markdown
Contributor

I believe this solves a similar, but different problem to synacor/preact-context-provider#3. preact-context-provider solves the merging issue when you are using <Provider config={}> at multiple levels in the tree. In order to have preconf play nicely with that, I think we have two options:

  1. Merge this PR, which makes the defaults that preconf provides act exactly as though you had wrapper the module in a <Provider config={defaults}> tag
  2. Modify preconf to actually wrap the component in a <Provider config={defaults}> tag when you apply the @withConfig decorator, so we don't make code that is redundant to Provider.
  3. Remove the ability for preconf to specify defaults at all and change the expectation to one where we expect you to provide defaults to your component through a <Provider> explicitly near the top of your app/component heirarchy.

Part of me leans toward #3 as I find the default functionality redundant with the new capabilities provided by <Provider>.

@apeltz

apeltz commented Mar 16, 2018

Copy link
Copy Markdown
Author

Going to close this PR after discussions with @billneff79 resulted in a new approach.

@apeltz apeltz closed this Mar 16, 2018
@billneff79

Copy link
Copy Markdown
Contributor

To be clear, I think our new approach will be to take the functionality that preconf provides and move it more generically into a new function in synacor/preact-context-provider as we've found uses, beyond config, where we'd like to be able to cherry pick values out of objects in context and provide them as props.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants