How to create a global context in Fresh Deno? - deno

I want to create a global instance of GunDB so that it only initializes once on the client side and I could then use it on any island.
I tried in index.tsx to simply add const gun = Gun() and send props to the island, the only problem is that then the island component does not see the Gun instance, which is normal because the Gun instance is initialized on the server side and not the client side.
In theory, it only needs a global context on the client side. Something like createContext() in react.

Fresh v1.1 adds Preact Signals support.
Preact Signals:
Signals are a way of expressing state that ensure apps stay fast regardless of how complex they get. Signals are based on reactive principles and provide excellent developer ergonomics, with a unique implementation optimized for Virtual DOM.
…
// Imagine this is some global state that the whole app needs access to:
const count = signal(0);
function Counter() {
return (
<button onClick={() => count.value++}>
Value: {count.value}
</button>
);
}
You can create a module that exports a signal for your global Gun instance:
import { signal } from "#preact/signals";
export default signal(Gun());
Then you can import this in any interactive island module to use it both server-side and client-side:
import gun from "./path/to/gun.ts";

Related

What is the lifetime of react context

I'm new to react. In the examples I've found so far, using the react context api, you create your own context object and hand it as value to providers, etc. All of the examples seem to store the entire context (either as one object or the sum of its parts) in state and utilize that for requests. But what is the lifetime of the object? Is it only created once during page refresh, or is it recreated during each render cycle such that it can only survive via useState or useRef? In other words, is useState actually needed to store the context data between render cycles, or is useState only being used as a way to subscribe to changes?
This is the way I've been creating context based on the tutorials I've seen...
(To be clear, my question is about the lifetime of the "contextData" object in context.js, and whether rerenders or state changes or some other lifecycle event causes the script including the contextData instantiation and createContext to be rerun, or if some other weird interaction between createContext, contextData, and useContext is going on.)
context.js
import React from "react";
const contextData = {
prop1: "something",
prop2: "somethingElse",
func1: someFunction(stuff) {
prop1 += ".";
},
};
const myContext = React.createContext(contextData);
export {myContext};
function MyContextProvider({children}) {
render <myContext.Provider value={myContext}>{children}</myContext.Provider>;
}
export default MyContextProvider;
index.js
...
root.render(
<MyContextProvider><App /></ContextProvider>
);
SomeComponent.js
import {useContext} from "react";
import {myContext} from "./context"
function SomeComponent() {
const ctx = useContext(myContext);
return <span>{ctx.prop1}</span>
}
This is a bit tautological, but the context object is re-created whenever the function that creates it runs again. The function will (almost always) be either a component or custom hook.
The React philosophy is that the view should flow from the state, so state changes result in (functional) components running again to determine how to change the view (if at all). The same is true if state is included in a context object - if a state setter inside the context object is called, the functional component enclosing the initializer of that state runs again, resulting in a new object being passed down to consumers.
In other words, is useState actually needed to store the context data between render cycles
Yes.
But what is the lifetime of the object?
One particular context object will generally be garbage collected once there's been a re-render and no children reference the old object in a stale closure.
All context objects will get garbage collected only after the component surrounding the context provider unmounts.
With regards to the code in the question - by mutating an object that gets passed down, you're breaking the standard React workflow, which should avoid mutation for those sorts of values. It would be far better to call .createContext in a parent component and to pass down a state setter that changes the prop1 property.
That said, if you don't do that - the top level of context.js only runs once, so you only create the object once, so that one object will exist forever. (which could be a mistake in case you ever change the code so that you want to use the context somewhere else too - the context value will include the old mutations)

Using vuex with Vue 3

Last year I spent some time learning Vue 2. I really enjoyed the framework but did not move forward with a project. I now have time for a project but I'd like to use Vue 3 with the composition API. I'll be using Firebase as the backend. I've seen conflicting techniques on whether or not to use Vuex.
For example, I'd like to store a "currentUser" object in global state that can be accessed from any component in the app. Normally, it would be done using Vuex. I'd have a getter to return the object, an async action to get the data from firebase and a mutation to set the state.
However, I've seen several Vue 3 code examples that do not use Vuex at all, instead they do something like this to get/set a currentUser in an app wherever it is needed for example in a navbar component.
composables/getUser.js
import { ref } from 'vue'
import firebase from 'firebase/app'
// refs
const user = ref(firebase.auth().currentUser)
// auth changes
firebase.auth().onAuthStateChanged(_user => {
console.log('User state change. Current user is:', _user)
user.value = _user
});
const getUser = () => {
return { user }
}
export default getUser
With this little bit of code above, I'm able to import getUser.js and access the currently logged in user using code like this. Also, the user object is now reactive:
<script>
import getUser from '../composables/getUser'
export default {
setup() {
const { user } = getUser()
return { user }
}
}
</script>
It seems I can use these little functions to get data from db directly without the need to use the Vuex pattern, which I find to be a bit more complicated.
So, my question is - if I'm starting a new Vue 3 project, is it ok to create "composable" functions to get/set data and import them into my components instead of using Vuex? Are there any downsides to this method? Or should I just stick with Vuex?
Short answer - You don't need it.
Long answer - It depends.
It depends mostly on your app and how often do you use "currentUser" data inside your components. If it's in 2 or more components, how often do you want to perform actually fetching from backend?
Once on app-init/login or every time each component mounts?
(probably once)
Does it need to be reactive? If yes - then you'll probably use centralized data pattern, your own or a library. Taken that into consideration it's probably more simple to just use Vuex.

react-redux connect should have side effects?

I have a component which need logged-in user data but in this component I'm not sure if user is logged in yet or not
is it a bad practice to check existance data in mapStateToProps and redirect to login page if needed? is it a side effect?
what about fetching data which is nit exist in state yet?
how should I handle such problems?
what should we do in mapState and what we shouldn't do?
is there any good practice for it?
it a bad practice to check existance data in mapStateToProps and redirect to login page if needed?
I am not sure of whether it's a best practice or not, but if we look at the semantics of mapStateToProps, it's main usage is mapping redux state to component props.
So in that sense anything that is not mapping can be considered a side-effect.
If you want to align with redux-way then you pass down with mapStateToProps properties that you want to react to, and you change those properties with mapDispatchToProps.
So in your case you would have some sort of Authentication service, that would have methods like login, logout, register, which would dispatch actions to your redux store, and in mapStateToProps you would subscribe to something like isAuthenticated.
And in your render you would check if this.props.isAuthenticated ? <PrintSome> : null
You can also check this tutorial with basically same idea, but taken out into a higher order component for reusability https://medium.com/quick-code/adding-authentication-to-react-redux-firebase-app-f0efcb1c519a
So let's assume you have defined your routes in the src/components/App.js component. You are at a point where you need to ensure that your App component knows whether or not the user is actually signed in at all.
Let's also assume that you have already developed a reducer in reducers/auth.js to record whether a user is signed in or not and you have assigned the authReducer to your auth piece of state.
At this point, inside your src/components/App.js file you would need to import:
import { connect } from 'react-redux';
Then at the bottom of your App component you need to define your mapStateToProps like so:
function mapStateToProps(state) {
return { auth: state.auth }
}
export default App;
So what I am recommending above is that you pass state to mapStateToProps and then return an object with a key of auth and that will take whatever value is coming out of the authReducer.
Then you take the connect() function you imported and pass mapStateToProps to it like so:
export default connect(mapStateToProps)(App);
So now your App component knows whether or not the user is signed in.
So what is an advantage of implementing the above? Well, it gives you the flexibility of determining what to display in your view depending on whether the user is signed in or not. For example, a sign-in/sign-out button.
You can now develop that button with a helper method that has a conditional like so:
renderButton() {
if (this.props.auth) {
return (
<button>
Sign Out
</button>
);
} else {
return (
<button>
Sign In
</button>
);
}
}

What Redux mean by there is one particular function take the whole state of the application?

I just start learning how redux work :
What redux mean by there is one particular function take the whole state of the application and action is been dispatched and return the whole new state of the application?
is this is visible on Enterprise level application Single Page Application ERP system or I have misunderstood something?
also how the function be pure and change in the previous state " use ref of the previous state and add to it new data then return this as an object?
if it is not is that will not affect the speed of the system to copy each time the whole system state for ERP system?
the course in which I get this info 1
the course in which I get this info 2
Redux in general
In redux, your app's state is represented as a single object which is passed to your app.
This single object is constructed by a single function which is called reducer. This function takes the current state and current action as arguments and returns a new object which represents the new state changed after the action is reduced.
It's kinda similar to Array.prototype.reduce where you get current accumulator (current state) current array entry (current action) and return new accumulator (new state) depending on what is the current accumulator and entry (state and action).
Combining reducers
Nevertheless, this doesn't mean you need to put all of your app's logic in one function. Redux has a helper combineReducers to let you write reducers for different parts of your state and then combine them into single reducer that constructs a single state object.
For example for a blog app with posts and comments, you can use it like that:
import { combineReducers, createStore } from 'redux';
import postsReducer from './postReducer';
import commentsReducer from './commentsReducer';
const rootReducer = combineReducers({
posts: postsReducer,
comments: commentsReducer,
});
const store = createStore(rootReducer);
Where postReducer and commentsReducer are two separate reducers each handling their part of the state.

How to have multiple reducers trigger updates based on a common set of actions without repeating yourself?

I would like many different redux actions in my app to all trigger common functionality in a specific reducer. I would like to avoid having to either repeat some flag in every action creator (like doThing: true) that the reducer looks for. I also don't want to have to have the reducer just look for every individual action that falls into this category, since that also requires someone to remember to do this every time they add a new action, like adding the flag.
I was thinking of dispatching a second action every time one of these actions is going to be dispatched. This would not be hard to do, but I'd rather not have 2 actions dispatched every time one thing happens. It seems like it would pollute the state history.
Is there a common way of solving this problem?
For more context to my specific problem, the specific feature is related to the API client my app uses to talk to our API. On every successful response, we'd like to do something in a reducer to update the state, and on every failed response, we'd like to do something else.
There are many different success and failure actions (such as ITEM_FETCH_SUCCESS or WIDGET_UPDATE_FAILURE), and adding a flag to all of them would be hard to remember to do when new ones are added.
Since all api requests go through a single function, that function COULD dispatch generic REQUEST_SUCCESS and REQUEST_FAILURE actions. But this would mean every response from the server would dispatch 2 actions (REQUEST_SUCCESS and ITEM_FETCH_SUCCESS). This is obviously not ideal since it would mean many more actions in my state history.
Assuming the generic REQUEST_SUCCESS and REQUEST_FAILURE actions are updating their own specific portions of the state-tree then it is fine to dispatch them as distinct actions. Doing this does not necessarily imply the pollution of your state history but can simply be a better description of the app's intentions.
ITEM_FETCH_SUCCESS: Change state for item
REQUEST_SUCCESS: Change state for request
WIDGET_UPDATE_FAILURE: Change state for widget
REQUEST_FAILURE: Change state for request
You can see that whilst the actions are intimately related, they are not necessarily the same thing as they change different parts of the state tree.
Accepting this, the question is: How best to implement the action-pairs so that adding new actions does not mean remembering to add its corresponding REQUEST_* partner?
I would consider applying a simple redux middleware component. This could intercept the return from your api and dispatch the appropriate REQUEST_* action automatically.
Here is an example from some live code. This middleware intercepts a disconnect event raised by a websocket and automatically dispatches a custom action as a result. It at least shows the principle:
//Dispatch a disconnect action when the websocket disconnects
//This is the custom action provided by the middleware
import io from 'socket.io-client'
import { actions } from './action'
const websocket = ({ websocketUrl }) => store => {
const socket = io(websocketUrl)
socket.on('disconnect', () => store.dispatch(actions.disconnect()))
}
export default websocket
//Apply the custom middleware via the redux createStore function
//Also include the thunk middleware because it is useful
import { applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import websocket from './middleware'
function websocketize (opts) {
return createStore => (reducers, initial, enhancer) => {
const middleware = applyMiddleware(thunk, websocket(opts))
return createStore(reducers, initial, middleware)
}
}
export default websocketize
// Create the top-level redux store passing in the custom middleware enhancer
const opts = {websocketUrl: env.WEBSOCKET_URL}
const store = createStore(reducers, websocketize(opts))
This implementation keeps everything inside your reducers as opposed to having logic outside in an interception(middleware). Both ways are valid.
Try a sub-reducer pattern. I usually feel gross when I see it used(because it is usually used wrong), but your situation sounds perfect.
Extract duplicate functionality out of your reducers to one single
sub-reducer.
Then pass that reducer as a function to all others that need it.
Then pass the action and state onto the sub-reducer.
The sub-reducer does it's thing and returns that slice of state to
your parent reducer to allow you to do whatever you want with it
there (ie return it, mutate some more, some logic).
Also if you are tired of worrying about typing out "all the stuff" for async then I highly recommend you try out redux-crud.js
It also is possible and a simple way to do that would be to give every action to one reducer and let it do that common mutation, in a single case:
case actionOne
actionTwo
actionThree
actionFour: {
//do common stuff here
}
. But you said it is not duplicated, it is similar, which means your case becomes complicated by branching logic. I also don't recommend this. Keep cases simple so you can easily catch invalid mutations. This should be a super power of redux that it is easy to catch mutation errors. And for this reason and many others I don't recommend normalizing data in the front end.

Resources