React native function getting global scoped inside functional component - react-native

Why my functions inside the functional components are getting global?
file1.js:
const Home = () => {
sayHello = () => {
console.log("Say Hello from Home")
}
}
export default Home;
file2.js:
const Settings = () => {
sayHello()
}
export default Settings;
Why my sayHello() function is accessible in the Settings screen

This is because you declared it globally (without a var/let/const) in front, so you attached it to global scope which is window:
const Home= ()=>{
sayHello=()=>{
console.log("Say Hello from Home", this === window)
}
}
Home()
console.log(sayHello())
Simply change it to const sayHello = () => {} to make it local to the scope.

Related

React createContext running mutation function not working correctly

I am having a problem i can't seem to understand why is happening since i have the same example working in codesandbox, but in my app it shows a different behavior. In my app i can see the context from the consumer both the bool and the function, but when i run the function it runs the empty function "setUpdate: () => {}" instead of running the "updBool()" in UpdateDataProvider.js file. Anyone know why this behaviour happens.
(component.js is not my actual file just a short example of how im using the context)
UpdateDataProvider.js
export const UpdateDataContext = createContext({
update: false,
setUpdate: () => {},
});
export function UpdateDataContexProvider({ children }) {
function updBool(bool) {
setU({ ...u, update: bool });
}
const [u, setU] = useState({ update: false, setUpdate: updBool });
return (
<UpdateDataContext.Provider value={u}>
{children}
</UpdateDataContext.Provider>
);
}
useUpdateData.js
import { useContext } from 'react';
import { UpdateDataContext } from '../../context/updateDataContext';
export function useUpdateDataContext() {
return useContext(UpdateDataContext);
}
component.js
import { UpdateDataContexProvider } from '../../context/updateDataContext';
import { useUpdateDataContext } from '../../hooks/exports';
useEffect(() => {
// loging the context shows me update bool and setUpdate function
console.log(context)
// Running the function will run the empty function in createContext
// in UpdateDataProvider.
context.setUpdate(true)
}, [])
export default Home = () => {
const context = useUpdateDataContext()
return (
<UpdateDataContexProvider>
<Other />
</UpdateDataContexProvider>
)
}
Don't mind my question, the mistake was that i was trying to run the function in useEffect in the home component but not the childs

why chatMsgStore.addChatMsg(bdmsg) does not effect the store?

store.js
import {useLocalObservable} from "mobx-react-lite";
function chatStore() {
return {
chatmsg: [],
setChatMsg(arr) {
this.chatmsg = arr
},
addChatMsg(msg) {
this.chatmsg.push(msg)
}
}
}
export const useChatStore = () => useLocalObservable(chatStore)
app.js
const App = () => {
const chatMsgStore = useChatStore()
const AppFunctions = {chatMsgStore}
useEffect(() => {
socket.on(activechat.chatid, (bdmsg) => {
chatMsgStore.addChatMsg(bdmsg)
})
return () => {
socket.off(activechat.chatid)
}
}, [activechat, chatMsgStore.chatmsg])
return (
<>
<AppContext.Provider value={AppFunctions}>
.....................
</AppContext.Provider>
</>
)
}
export default App;
fetch.js
async function getChatMessages(url, body, userStore, chatMsgStore) {
........
chatMsgStore.setChatMsg(firstResData)
........
on app load i add a socket listener which deps are activechat and chatMsgStore.
this listener is dynamic and must be changed when deps change.
the only purpose of this listener is to add a msg to the store and re-render the observer component
deps :
activechat - non store state
chatMsgStore.chatmsg - store state
why chatMsgStore.addChatMsg(bdmsg) does not effect the store? so deeply nested components inside App.js is not re-rendering.
otherwise i have a function getChatMessages which i import from custom hook deep inside App.js which sets the messages. this func is not a child of App.js and it is not wrapped with observer chatMsgStore.setChatMsg(firstResData) works! i can set the message so the observer component will re-render
how to make this code in useeffect above work?
Your App component is not wrapped with observer HOC so it won't react to observable values changes.
Wrap it like that:
const App = observer(() => {
// ...
})
or when exporting:
export default observer(App)
More info in the docs
you should use autorun from mobx in order to set correctly the reactivity in useEffect, here is a link to the doc that explains why and how use it.
But I think that you should not put chatMsgStore.chatmsg inside the deps array because you're not using it inside the useEffect.
If you can provide a working example maybe we can help you further.

Server side singleton injection in Nuxt

I need a shared object (e.g.cache/logger/service) instance (singleton) on serverside accessible to SS middleware/plugins/nuxtserverinit.
I have tried a local module which tries to inject $cache in serverside context during render:done hook (see below), but no matter what I tried it still was not available during SS request processing.
// modules/myCache.js
export default function(_moduleOptions,config) {
this.nuxt.hook("render:before", context => {
const cache=new myExoticCache()
// I tried all the below combinations
context.nuxt.$cache1=cache
context.serverContext.$cache2=cache
context.options.$cache3=cache
context.globals.$cache4=cache
});
this.nuxt.hook("render:done", context => {
// tried the above here too
});
}
// plugins/myplug.js
export default ({serverContext,nuxt}, inject) => {
//all of the below are undefined
//nuxt.$cache
//serverContext.$cache
}
Seems like I am missing something. Would be great to find out what.
How can I pass value from route:done hook to any server-side middleware/plugin/nuxtserverinit.
You can extend ssrContext from 'vue-renderer:ssr:prepareContext' hook.
// modules/myCache.js
export default function(_moduleOptions) {
const $cache = 'CACHE';
this.nuxt.hook('vue-renderer:ssr:prepareContext', ssrContext => {
ssrContext.$cache = $cache;
})
}
// plugins/myplug.js
export default function ({ ssrContext }) {
if (process.server) {
console.log(ssrContext.$cache)
}
}

How to use react-i18next inside BASIC function (not component)?

I know that react-i18next work in every component: functional (with useTranslation) and class component (with withTranslation()) BUT I can't use translation inside a basic function like this:
const not_a_component = () => {
const { t } = useTranslation();
return t('translation')
};
const translate = not_a_component();
ERROR HOOKS !
Thanks !
You could just use i18next library for translation using javascript.
react-i18next is just a wrapper library on top of i18next.
Below is an example if you are already using react-i18next and it is configured.
import i18next from "i18next";
const not_a_component = () => {
const result = i18next.t("key");
console.log(result);
return result;
};
export default not_a_component;
If you opt to use only i18nextthen you could simply get t function.
It all depends upon your requirement.
import i18next from 'i18next';
i18next.init({
lng: 'en',
debug: true,
resources: {
en: {
translation: {
"key": "hello world"
}
}
}
}, function(err, t) {
// You get the `t` function here.
document.getElementById('output').innerHTML = i18next.t('key');
});
Hope that helps!!!
Alternatively, you can pass t as an additional parameter:
const not_a_component = (t) => {
return t('translation')
};
// Within a component
const { t } = useTranslation()
not_a_component(t)

Async function support in Mithril.js for webpack dynamic imports?

I'm trying to figure out how to use dynamic import in webpack with mithril. To do that elegantly, I think I'll need to use an async function somewhere along the line. Right now this is how I have used the async function:
import m from 'mithril'
let App = async () => {
let { Component } = await import('./components.js')
return {
view () {
return m(Component)
}
}
}
App().then(app => m.mount(document.body, app))
Ideally, I want to use it like this:
import m from 'mithril'
let App = {
async view () {
let { Component } = await import('./components.js')
return m(Component)
}
}
}
m.mount(document.body, App)
Is there something I've been missing from the documentation to acheive what I'd like to do? I've tried to look at every mention of promise, but it's possible that I've missed this.
Any help would be appreciated.
One way that should work is this:
async function main() {
const myModule = await import('./myModule.js');
const {export1, export2} = await import('./myModule.js');
const [module1, module2, module3] =
await Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
]);
}
main();
(async () => {
const myModule = await import('./myModule.js');
})();
For further information follow the link below.
ES proposal: import() – dynamically importing ES modules
Try the following, which provides a simple component named DynamicComponent which can be used anywhere and with children:
App.js
import m from 'mithril'
import { DynamicComponent } from './DynamicComponent'
const App = {
view() {
return m( DynamicComponent, {
component: 'OtherComponent'
}, 'Hello world' ),
}
}
}
m.mount(document.body, App)
OtherComponent.js
import m from 'mithril'
export function OtherComponent() { return {
view({ children }) { return m( 'div', children )}
}}
DynamicComponent.js
import { hooks } from '/hooks'
export function DynamicComponent() { return {
...hooks,
attrs: null,
component: null,
view({ children }) { return (
// Await module resolution and process attributes.
// Use '&&' as a shortcut to only continue
// once 'this.component' isn't null.
// Pass a clone of attrs to the loaded component.
this.component && m( this.component.default, this.attrs, children )
)}
}}
hooks.js
async function oninit({ attrs }) {
// Preload -> Load immediately, in parallel
// Prefetch -> Load when browser is idle (Can be less responsive)
// See more: https://webpack.js.org/guides/code-splitting/#prefetching-preloading-modules
// Dynamically import component and append '.js' (Don't include '.js' in your imports).
if ( attrs.loadType = 'prefetch' ) {
// Lazy load
this.component = await import( /* webpackPrefetch: true */ `
${ attrs.component }.js`
)
} else {
// Immediate load
this.component = await import( /* webpackPreload: true */ `
${ attrs.component }.js`
)
}
/*
Process and pass along attributes
This clones the attributes to prevent any changes from affecting
the original attributes.
You can save memory if it becomes a problem by directly
assigning `v.attrs` to `newAttrs`, but you lose this immutability.
*/
const newAttrs = { ...v.attrs }
// Remove attributes used in `DynamicComponent`
delete newAttrs.component
delete newAttrs.loadType
// Assign to component
this.attrs = newAttrs
m.redraw()
}
export const hooks = {
oninit,
}