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
What documentation would you like to see here? #531
Comments
First of all I think it is important to have short installation instruction (getting started) and browser support list on the front page (the main README.md I mean). Also could be useful to have documentation TOC there too, make introduction for users as useful as possible, you still may keep readme short by using [more] links to docs. Few uncovered things in docs I can imagine right now:
|
Having recently read several projects docs as a newbie I must say Vue have been the quickest to digest and left me with the least number of open questions. |
How to create reusable modules, how to share, how to make ensure it doesn't break someone else's app if they use your module. |
The open questions I have for Hyper App having read around and looked at the samples are
Hope that helps |
I would like a more detailed explanation of hydration, the current docs don't make it clear how you should set up html to be used by hyperapp. |
Since the library is so small and I understand a major goal is to keep it that way I would like to see annotated source code like for underscore.js. This will greatly help new users/contributors dive into the codebase and figure out how things work or identify bugs. |
@timjacobi That's really cool! I never knew that was a thing haha 🎉 |
@Ch4s3 How much clear the hydration docs would need to be? The process is extremely simple, hence the extremely simple docs. What (part) wasn't clear? |
@jorgebucaran Yeah, I think I get the idea, but in practice it didn't seem to work when I tried it. The example html in the docs is presently: <html>
<head>
<script defer src="bundle.js"></script>
</head>
<body>
<main>
<h1>0</h1>
<button>–</button>
<button>+</button>
</main>
</body>
</html> Should the contents of import { h, app } from "hyperapp"
const state = {
count: 0
}
const actions = {
down: () => state => ({ count: state.count - 1 }),
up: () => state => ({ count: state.count + 1 })
}
const view = (state, actions) => (
<main>
<h1>{state.count}</h1>
<button onclick={actions.down}>-</button>
<button onclick={actions.up}>+</button>
</main>
)
export const main = app(state, actions, view, document.body) Can I render to just a div that contains |
Yes.
Yes. The given example replaces the page body because the given container is // This is your server side rendered HTML.
document.body.innerHTML = `
<div id="app"><main><p>foo</p></main></div>
`
// And this is in your bundle.js
app(
state,
actions,
state => h("main", {}, [h("p", {}, "foo")]),
document.getElementById("app") // <= Any container you want!
)
Yes. Imagine your SSR HTML looks like this: <div>
<div id="reactapp">
...
</div>
<div id="vueapp">
...
</div>
<div id="hyperapp">
<main>
<h1>0</h1>
<button>–</button>
<button>+</button>
</main>
</div>
</div> All you need is pass |
Awesome, thanks @jorgebucaran. |
Hey @Ch4s3 how about a PR adding that info to the docs? :) |
@SteveALee If it can be better re-worded and re-written, that would be 💯 |
Working examples with playground like Try Elm which is centrally/regularly updated, because examples allover the internet are mostly non-working... |
@kosirm Thanks for your feedback. Do you have something more specific in mind? The question is what kind of documentation would you like to see on this repo, but your suggestion sounds more like the kind of learning resources you wish were available, which is fine, but not the kind of feedback I am trying to collect. |
Oh, I see Higher Order Apps (wrappers?) are a thing. Need documenting |
sorry for misunderstanding topic... Thanks for understanding 👍 |
I have been using What I would like to see, is a "cookbook" style of document. What I mean by that is e.g the usage of a helper So my suggestion basically boils down to the addition of a separate document, where all common tasks related to various use-cases can be appended incrementally. Thus, alleviating the pain of developers coming from other frameworks, as well as those accustomed to non-functional programming paradigms. BTW, state mutation is bad, should it be allowed in the awesome list? |
Thanks @kenOfYugen! 😌 They caught you @marcusasplund! 🚔 😉 |
@kenOfYugen Thx for the heads up, please review |
Maybe something on the approach to node checking (#378)? I imagine something small in the Virtual Nodes or Component section would suffice. |
When no validation is needed, I might as well use jQuery events for forms. |
I think it would be helpful to mention that the return value of app() is the wiredActions object. I didn't want to pass all the actions down the tree and in the code I found that I can just use the result of app() to export this object and use these wired actions in my components via importing them. Also an example for this would be helpful. At least I couldn't find that in the docs. |
@mightyplow I admit it could be much better, but it's there. :) |
@jorgebucaran sorry, my bad. Well done! ;) |
Explain the different type of
|
@Siilwyn This should be better documented, but API symmetry is one of the reasons. I want to call actions the same way that I define them. const actions: {
myAction: data => ...
} so actions.myAction(data) |
But then why do actions take only one argument? What if one were to pass extra parameters? |
@rhbecker state mutation is in general a potential source of errors. For For the time being, I suggest reading all the current documentation, and replicating the examples on your own. You' ll be fine! There is no such thing as a good |
I also keep grabbing the following code snippet for reference, would be good to see in the actions documentation: const actions = {
setter: data => data,
getter: () => state => state,
reducer: () => state => state.count + 1,
notmutating: () => { ... },
async: () => (_, actions) => { actions.done() }
} by @Swizz |
I do think we need to document the two different action signatures a lot better. I'm not sure I agree with static vs dynamic for the naming since both take a dynamic We also need to make more than a single casual reference to state immutability in the actions section:
I believe this should be super prominent and mentioned as part of state. |
@kenOfYugen: Sorry if this was unclear from my last post. I wasn't literally asking why state mutation is bad. The point I was trying to make is that there are presumably some principles behind hyperapp - the arrangement of implementation into state, action, view, what ideally belongs in each of these, and what does not, etc. So far, existing docs seem light on the why. If I arrive here from some other framework or library that uses a different paradigm, and I don't understand the why of hyperapp, I might end up doing things I don't realize are incompatible with that why. |
I am working on a couple of articles to improve the documentation ecosystem and maybe some of that will find its way into the official documentation as well. I was also thinking it would be nice to have a User's Guide, that teaches you only how to use Hyperapp without bogging down on details, like what is a VDOM, etc. @rhbecker Hyperapp is probably one of the least intrusive "frameworks" out there, and this is not accidental but by design! 😉 I’ve always been unenthusiastic to learning a big framework. Not because they aren’t great, but on the fact that I like to know how things work "beneath the surface" and that I'm coding my own JavaScript, not the JavaScript <insert framework here> wants me to use. The meat of it is I want to grow skills in JavaScript, not skills into frameworks. Especially when that framework may be replaced in a few of years (if not months 😮). I want transferable skills, not obsolete skills. |
I'm not certain how much of @jorgebucaran's last reply was in response to what I've said. FWIW, I'm reading everything after mention of me as such. It's great that hyperapp is "minimal", "simple", "non-intrusive", "light on opinion" and all the rest. You already do a great job marketing that aspect. It's what piqued my interest, and why I'm here trying to answer the original question of this thread. But you know what's smaller than 1 KB? 0 KB. And what's even less opinionated? No opinion at all. There's a reason to use hyperapp, instead of nothing, right? There's a reason you've chosen to arrange your applications into state, actions, and views. You whittled it down to the smallest amount of opinion you felt was necessary - so why is what is still there still there? There's a reason @kenOfYugen said:
And that @jorgebucaran followed that with:
Are you expecting @marcusasplund to be the last hyperapp user to make such a mistake? Providing some insight for how to deal with state isn't intrusive. It helps users of hyperapp understand why they are bothering with hyperapp, and helps them use it more effectively - helps them get the most value out it. The README says:
Ok, but why? What about The Elm Architecture is commendable? Why should using a functional paradigm be appealing to me, as someone surveying my options? It might be the case that you're expecting your audience to find you after already coming to the same realizations you did when you decided to make hyperapp. In that case, maybe the why is superfluous. But at least some folks are gonna happen upon hyperapp without understanding why any of this is good. In my opinion, the current state of the documentation does not get into that enough to satisfy that sort of audience. Does that make any sense? |
I was just playing with Marcus. Don't take it so seriously. 😉
IMO the current documentation is not very good, that's why I created this issue, and I appreciate your feedback. |
Telling you why FP is nice is out of the scope of Hyperapp's documentation. Talking about that is better suited for an opinionated blog post.
Telling you what parts of TEA we embrace and what not would be a good idea. In the future, however, I want to stop marketing this so heavily, since we have diverged considerably from TEA. Right now I see Hyperapp as a "pragmatic TEA-inspired approach to state management + built-in VDOM engine". But to answer your question, TEA inspired the very successful Redux as well as many similar spinoffs architectures, e.g., Vuex. Aso, from Elm's guide:
|
Even so knowing the design decision is very interesting to know and can be educational when writing our own code using ha. But I agree it should not be part of the core doc. Part of the extras or a linked blog post |
@jorgebucaran I came to Hyperapp after reading your post on SitePoint. It came at just the right time because I had been learning React and just been reading about Redux and why it was useful. The Redux site introduction did a good job about explaining why having a state object as a single source of truth and dispatching actions being the only way of updating that state. It made sense, but wiring Redux up to React seemed like quite a bit of work, especially for a simple app. Then I read your blog post and saw a tiny JS library that seemed to do what React + Redux did in less code and a simple to use API. I'm not sure I would have appreciated what you had done if I hadn't read the Redux pages though. Given this - I'd second what @rhbecker said - it would be nice to have something similar to the Redux pages for Hyperapp that explains the motivation behind the principles used by Hyperapp and some common use cases. |
Havent read the whole thread, so don't know if it's been mentioned already, but: |
Hi, I would like to see more explanations about actions. Sometimes I don't understand how they work. For example with this action const myaction = () => async state => //blahblah... page does not refresh and nothing happens, no error, just nothing. I'm looking for a reason for an hour and then spontaneously remove |
@algebraic-brain In the case of your async function, it returns a When you define an async action, you need to call regular, synchronous actions to update the app state & trigger re-draws. The "Gif Search" tutorial in the docs is a good example -- see the Hope that clears things up for you! 😄 |
@SkaterDad Thanks a lot, but my idea is that your explanation should be located directly in the documentation. Of course i've seen the "gif search" example but I was unable to deduce right understanding from that tutorial. Or i missed something? |
@SkaterDad Thanks for explaining. @algebraic-brain I added it to the docs and will push this soon with a few other changes. I hope future arrivers will not go through this pain. Thank you, both! |
Firstly, I think hyperapp is awesome! I agree with @zaceno about having a dedicated actions page in the docs. One specific challenge I had, and I think many other users of hyperapp will run into, is how to correctly update deeply nested state in an immutable way. From hello-world.md:
This makes sense, but I didn't fully understand what this implies right away about the process of updating deep state. I think that some example of how this comes into play would improve comprehension of how actions should be created. From what I understand, the pattern employed (when state slices can't get all the way to the nested level) is to use the spread operator to re-create the entire object sub-structure of a slice of state. For instance, in one case I needed access to a higher-up state for something (currentTeamCollection below, in my case) so I employed the spread-operator to compose the nested levels of the new immutable state-slice (which I learned via browsing hyperapp issues and PRs) const state = {
user: {
currentTeamCollection: 'test',
teamCollections: {
'test': {}
}
}
}
const actions = {
user: {
addTeamToCurrentCollection: team => state => {
let tc = state.teamCollections[state.currentTeamCollection]
if(!tc[team.name]) tc[team.name] = team
return {
teamCollections: {
tc,
...state.teamCollections
},
...state
}
}
}
} This solution of updating nested state as shown above took me awhile to figure out, and I think many people would benefit from some sort of guidance of how to update deep state. Maybe to the more experienced, this process is common sense (or there is a better way) but I think many would benefit from an example of this being done. If the docs had a tutorial that showed an example of deep state, and actions that updated the deep state, I think it would be helpful. Currently all three tutorials on the docs have shallow state only. I think the actions page should also make clear the function signatures that actions are supposed to comply with. I didn't realize that actions are designed to accept one parameter only, and this confused me for awhile, until I read into the issues and PRs. I hope these thoughts can help specifically with making actions more quickly understood by new users. Thanks for reading! |
@CanyonTurtle Just confirming, did you know you can do this? const state = {
deeply: {
nested: {
value: 1
}
}
}
const actions = {
deeply: {
nested: {
multiply: by => state({ value: by * state.value })
}
}
} |
True, true! 🙇
I'll document this! 👍 |
const state = {
valueHere: 4,
deeply: {
nested: {
value: 1
}
}
}
const actions = {
deeply: {
nested: {
// how can I access valueHere in this action?
multiply: by => state({ value: by * state.value })
}
}
} Thanks for the response time! It's just that I don't know how to use higher-up state. |
@CanyonTurtle You can't! There is no way What you coulld do is nest all those objects inside a common parent object and have actions under that path manage the objects below. |
@jorgebucaran , Thanks for the clarification. I just think that what the documentation could also include an example of, is where there is a common parent object, managing its deep children. That is the situation similar to the code example I posted above in that long post, and what I am saying is that this case would be one worth explaining briefly. Specifically, // ...
return {
teamCollections: {
tc,
...state.teamCollections
},
...state
}
// ... I found this application of spread operators to update the layered state to be not immediately clear, and I am suggesting this as something to show an example of, or briefly cover in the documentation. Even though this deep-copying method is a natural conclusion from understanding javascript to a certain level, I think many users would get a running start from an example or two about it. |
@CanyonTurtle You are right. 👍 |
Thanks for listening! Hyperapp is awesome again. |
@jorgebucaran Annotated hyperapp source could be really useful for newcomers |
Where did you guys land on the lazy loading stuff? I tried to follow it through the past issues chain but I got lost in the references and closing... Does anybody have an example? |
@brandonros I believe the current option is using a higher order function of the app function (HOA). |
The goal of this issue is to collect feedback about what stuff should be covered in the official documentation.
The text was updated successfully, but these errors were encountered: