Skip to content
This repository has been archived by the owner on Apr 29, 2023. It is now read-only.

Add key to the element wrapped in the Route #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ForsakenHarmony
Copy link

@ForsakenHarmony ForsakenHarmony commented Jan 15, 2018

Fixes #38

@codecov
Copy link

codecov bot commented Jan 15, 2018

Codecov Report

Merging #40 into master will increase coverage by 3.33%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #40      +/-   ##
==========================================
+ Coverage   37.73%   41.07%   +3.33%     
==========================================
  Files           6        6              
  Lines          53       56       +3     
  Branches       12       14       +2     
==========================================
+ Hits           20       23       +3     
  Misses         24       24              
  Partials        9        9
Impacted Files Coverage Δ
src/Route.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7343784...4ea7821. Read the comment docs.

package.json Outdated
@@ -24,12 +24,15 @@
"bundle": "rollup -i src/index.js -o dist/router.js -f umd -mn router -g hyperapp:hyperapp",
"minify": "uglifyjs dist/router.js -o dist/router.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=router.js.map",
"prepublish": "npm run build",
"format": "prettier --semi false --write 'src/**/*.js'",
"format": "prettier --semi false --write \"src/**/*.js\"",
Copy link
Owner

Choose a reason for hiding this comment

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

@ForsakenHarmony Are you on windows? What's the purpose of this? Just curious.

location: location
})

child.props.key = child.props.key || props.path
Copy link
Owner

Choose a reason for hiding this comment

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

@ForsakenHarmony @zaceno Is this infallible?

Anyone familiar with ReactRouter, what's going on there?

I like this though.

Copy link
Author

Choose a reason for hiding this comment

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

props always gets added by h at least, if that's what you're asking

Copy link
Owner

Choose a reason for hiding this comment

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

Nope, I mean does ReactRouter also add a key to the route component?

Copy link
Author

Choose a reason for hiding this comment

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

afaik, no, but they have component methods, which don't depend on elements that might be reused

Copy link
Contributor

Choose a reason for hiding this comment

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

@jorgebucaran is it infallible? ...well... this:

<main>
   <Route path="/show/secrets" render={SecretComponent} />
   <AComponent />
   <AnotherComponent />
   <Route path="/show/secrets" render={AnotherSecretComponent} />
   <ThirdComponent />
</main>

I e using the route as a switch to turn on or off multiple sibling components. Then the siblings will be keyed with the same key which of course is no good. ...unless the components have their own keys, in which case those keys will be used instead. So:

A - Before: By default oncreate won't get called for routed components. You have to manually key them to make it work. Beginners are required to understand the relationship between keys and lifecycle events. Higher threshold.

B - This proposal: You get automatic keys which make sense for the most part. And hence a lower threshold for beginners. But you run the risk of key-collisions and you don't understand why.

Copy link
Owner

Choose a reason for hiding this comment

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

What about this?

var key =
  props.key ||
  props.path + (props.render ? props.render.name + props.render.length : "")

Copy link
Owner

Choose a reason for hiding this comment

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

Arrow functions have no name. 😞

Copy link
Author

Choose a reason for hiding this comment

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

They do if you assign them to a variable, but anonymously used, they don't, just ""

Copy link
Owner

Choose a reason for hiding this comment

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

I guess we could use props.render.toString(), but that feels asking for trouble.

Copy link
Owner

Choose a reason for hiding this comment

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

Keys have a pivotal role in the VDOM, and instead of hiding this them, we should ask users to properly key their routes instead.

Only child.props.key = child.props.key should be fine, but that too is subject to what we do with jorgebucaran/hyperapp#555.

/cc @frenzzy

"release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
},
"babel": {
"presets": "env"
},
"jest": {
"testURL": "http://test/test"
Copy link
Owner

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

I wanted to do it in the test, but couldn't figure out how to do that

@@ -24,12 +24,15 @@
"bundle": "rollup -i src/index.js -o dist/router.js -f umd -mn router -g hyperapp:hyperapp",
"minify": "uglifyjs dist/router.js -o dist/router.js -mc pure_funcs=Object.defineProperty --source-map includeSources,url=router.js.map",
"prepublish": "npm run build",
"format": "prettier --semi false --write 'src/**/*.js'",
"format": "prettier --semi false --write \"src/**/*.js\" \"test/**/*.js\"",
Copy link
Author

Choose a reason for hiding this comment

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

I used normal quotes, because single quotes seemed to break it on windows

@lukejacksonn
Copy link

Could you provide a description explaining what this PR does and what problem you are trying to solve?

@ForsakenHarmony
Copy link
Author

#38

@lukejacksonn
Copy link

Thanks! So just to clarify the desired behaviour; in this case:

main([
  Route({ render: Nav }),
  Route({ path: '/users', render: () => div({ key: 'users' }, 'Some Users:')  }),
  Route({ path: '/users/:id', render: User }),
])

The first route gets no key
The second inherits its key users
The third route gets the key of /users/:id

Is this correct?

@ForsakenHarmony
Copy link
Author

Yea, I guess so

@lukejacksonn
Copy link

The path seems like a sensible key to use. It is a good identifier for the element. The only doubt I have; is it guaranteed to be unique? Does it even matter if it is not? If it does matter, how should we document it? Otherwise SGTM 👍

@ForsakenHarmony
Copy link
Author

it was mostly to address an issue I had with element reuse and oncreate not being called

would be the same thing with non unique paths ig

@jorgebucaran
Copy link
Owner

@lukejacksonn @ForsakenHarmony Zaceno explained it best here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
4 participants