add-use-state: Create useState magic#4417
Conversation
|
Out of curiosity, what's the difference between a state and the already existing Alpine.stores? I think the example we'll not run with the CSP build of Alpine, not sure if it makes more sense to show a fully functioning example if the aim is to help CSP complaint sites |
|
The difference between Alpine.store and $useState is that the store defines the data at a global level and $useState does it at a local level respecting the component hierarchy. The communication between Alpine components is quite poor and define global variables degrades it even more. |
|
To respect CSP, direct insertions into variables in the HTML are not allowed, for example @click="count++" |
|
I don't see why this should be a core plugin. the naming is also confusing for this use case. Does the current CSP build allow...function call expressions? Checked. It does not. So this still won't evaluate in expressions anyway. Instead of this, I'd really just prefer a more advanced expression parser build into the CSP evaluator. |
| // Register warnings for people using plugin syntaxes and not loading the plugin itself: | ||
| warnMissingPluginMagic('Focus', 'focus', 'focus') | ||
| warnMissingPluginMagic('Persist', 'persist', 'persist') | ||
| warnMissingPluginMagic('useState()', 'useState', 'use-state') |
There was a problem hiding this comment.
This looks like you're adding it to the core...
not as a plugin...
so which is it?
Definitely should not be a built in.
|
|
||
| test('useState initializes state with the given initial value', | ||
| html` | ||
| <div x-data="{ state: $useState('testValue') }" x-init="$el.setAttribute('x-data', state)"> |
|
|
||
| test('useState updates state correctly', | ||
| html` | ||
| <div x-data="{ state: $useState('initialValue') }" x-init="$el.setAttribute('x-data', state)"> |
There was a problem hiding this comment.
What is this init even doing?
It will just set x-data = [object Object]...
Right. In that case, I don't think it solves a big problem in Alpine that would suggest it's needed in the core or even as a first class plugin. x-data has already reactive data scoped locally, the state you define is just a wrapper around a variable. I had a good look at your PR and I can see why you do it, you are trying to define pure functions that only modify the state and you were not happy because you can't do it for things such as integer literals because they are not references in javascript (like objects are). <div x-data="{
count: 0,
state: {count: 0}
}">
<button
@click="increment(count)" // This does not work
x-text="count"
></button>
<button
@click="increment2(state)" // This work
x-text="state.count"
></button>
</div>
<script>
function increment(state) {
state++;
}
function increment2(state) {
state.count++;
}
</script>but in doing so, you are forcing people to use You may not agree with the approach but the Alpine way to do it (or at least one of them) would be to define the logic in your component and not in the global scope so it would look more like <div x-data="{
count: 0,
increment() {this.count++}
}">
<button
@click="increment"
x-text="count"
></button>
</div>or, for those not liking js in the html attributes (CSP build as well), something like <script>
document.addEventListener('alpine:init', () => {
Alpine.data('counter', () => ({
count: 0,
increment() {this.count++}
})
})
</script>
<div x-data="counter">
<button
@click="increment"
x-text="count"
></button>
</div>That being said, if you like the approach, you can use it in your own project. You can even publish a third party plugin for you to use in all your projects and for other likeminded people who likes the approach but I personally don't feel like it belongs to the core. |
|
I find your answer very interesting @SimoTod . You are right in what you say and I will add this tool as an external plugin. I think the most important use of this is to be able to modify the input parameters just like you do in increment2 in a consistent and simple way. |
PR Review: #4417 — add-use-state: Create useState magicType: Feature What's happening (plain English)This PR adds a new
Other approaches considered
All three existing approaches are simpler and already cover the stated use cases. Changes MadeNo changes made. This PR should be closed, not fixed. Test ResultsNo CI checks have been run on this branch. The tests in the PR are also broken — they call Code ReviewSeveral issues beyond the fundamental "should this exist?" question:
SecurityNo security concerns beyond the false claim of CSP compliance — the implementation doesn't actually solve CSP issues as described. VerdictClose. The community already reached this conclusion in the comments. A collaborator (@SimoTod) and a contributor (@ekwoka) both independently identified that this doesn't solve a problem Alpine doesn't already handle with The specific issues:
This adds permanent public API surface to Alpine for something that's already solvable with existing tools. Per Alpine's philosophy of simplicity, this should stay a third-party plugin if the author wants to maintain it. Reviewed by Claude |
Hello everyone.
I have created a new magic property to increase security in CSP-compliant developments.
Additionally, you can send variables by parameters to a function, change its value and have it extended.
I hope it helps you and I would love it if we could all improve this new implementation if necessary.