I want to create a list of functionalities that I can access easily from anywhere on my app by simply importing the component. Here is what my component looks like:
functionalities.component.jsx
import { AES } from "crypto-js"
import { useContext, useState } from "react"
import { ConfigurationContext } from "../env"
const {configurationState} = useContext(ConfigurationContext);
const Functionalities = {
encrypt: (info) => AES.encrypt(info, configurationState.application.key).toString();
}
export default Functionalities
The problem I'm facing now is that I'm not able to use any context values since it would cause an error. Is there a way to implement "useContext" on this?
You can call a React Hook only inside a React component or inside a custom hook, it's one of the rules of the hooks.
The best you could do, if you need to share common functionalities, is creating a set of custom hooks.
import { AES } from "crypto-js"
import { useContext } from "react"
import { ConfigurationContext } from "../env"
const Functionalities = {
useEncrypt: () => {
const { configurationState } = useContext(ConfigurationContext);
return (info) => AES.encrypt(info, configurationState.application.key).toString();
}
};
export default Functionalities;
Example usage (always remember to call useContext inside a Context.Provider).
function EncryptComponent({info}) {
const encrypt = Functionalities.useEncrypt();
return <button onClick={() => encrypt(info)}>Encrypt</button>
}
I provide a CodeSandbox example that show how to do that.
Related
I would like to return data in the form of a String, JSON object or integer, or any other data other a JSX component, but without breaking the Rules of Hooks. Is there a way to do this in React?
I need to go about it this way since I need access to React Hooks.
import {} from 'react-native';
import React, {useEffect} from 'react';
export function revGetUserEntities({revCallbackFunction}) {
let myData;
useEffect(() => {
// Set myData here, or do something with it before returning;
}, []);
return myData;
}
Thank you all in advance.
Create a custom hook
a common practice is use the word use before the name of your function
i would recommend to rename function to useRevGetUserEntities
import {} from 'react-native';
import React, {useEffect} from 'react';
export function useRevGetUserEntities({revCallbackFunction}) {
// let myDate; this will be undefined on rerender. use state
const [myDate,SetMyDate] =React.useState(null);
useEffect(() => {
// Set myData here, or do something with it before returning;
SetMyDate(your value)
}, []);
return [myData];
}
now you can reuse it in any other function without losing state or value on rerender
note you can also pass a callback function in hooks
const [myData] = useRevGetUserEntities((callbackValue)=>{
// revCallbackFunction from useRevGetUserEntities function will be
})
Edit you can also watch for myData change in parent Observe changes
this will enter code here fire once myData value changes in Parent function
React.useEffect(()=>{
if(myData !== null){
}
},[myData]
I am working on React web app using typescript, hooks. Each component
must have only one useSelector(), but actually I have 2 useSelector(),
Is there any solution for 2 useSelector() to be merged or something
else.
export default function UserInfo() {
const { city1, city2, city3 } = useSelector(cityNameSelector);
const { country } = useSelector(countryNameSelector);
.....
...
}
import { useState } from 'react';
export default function usePrivacyMode() {
const [isPrivacyOn, setIsPrivacyOn] = useState(false);
return {
isPrivacyOn,
setIsPrivacyOn
};
}
This is my custom hook. I set the state in PrivacyIcons component, and then I use isPrivacyOn for show/hide values from a table based on the value. But in a different component the isPrivacyOn is not changed, it's changed only in PrivacyIcons? Why I can't change it in one component and then use the value across all components? Thanks.
states are not meant to be shared across components. You are looking for useContext. This allows you to share a function and a state between components. React has an excellent tutorial on how to do it in the official documentation: https://reactjs.org/docs/hooks-reference.html#usecontext
For your specific example it would look something like this:
Your App.js
import { useState } from 'react';
export const PrivacyContext = createContext([]);
const App = (props) => {
const [isPrivacyOn, setIsPrivacyOn] = useState(false);
return (
<PrivacyContext.Provider value={[isPrivacyOn, setIsPrivacyOn]}>
<ComponentUsingPrivacyContext />
{props.children}
</PrivacyContext.Provider>
);
};
export default App;
Keep in mind that any component that wants access to that context must be a child of PrivacyContext
Any component that wants to use PrivacyContext:
import React, { useContext } from "react";
import {PrivacyContext} from "...your route";
const ComponentUsingPrivacyContext = (props) => {
const [isPrivacyOn, setIsPrivacyOn] = useContext(PageContext);
return (
<button onclick={setIsPrivacyOn}>
Turn Privacy On
</button>
<span>Privacy is: {isPrivacyOn}</span>
);
};
export default ComponentUsingPrivacyContext;
I have a plain javascript website. I'm importing with webpack a react component and use it in the website.
The problem is the component only works if I import react(globally).
I only use this component once in a while so I only want to import react if needed.
I'm interested in such a thing:
if(some_condition){ import react and import my component}
How could I do this?
Thanks
You can do dynamic imports like this:
(async () => {
if (somethingIsTrue) {
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
}
})();
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports
You can use dynamic import.
if (condition) {
Promise.all([
import("react-dom"),
import("react"),
import("path/to/component"),
])
// if you use named export for component, just use name instead of `default`
.then(([{ render }, { createElement }, { default: Component }]) => {
// select element where you want to render
let root = document.getElementById("root");
// render your component
render(createElement(Component), root);
});
}
I have a component documents with a button, which onClick calls an action createDocument. The action returns a payload (on success) with id of the new document and then we have to route to the newly created document route /documents/:id
Now the way I have set it up right now, is not by using the Redux state at all, but simply by using the promise in the component to get the action and then making the route change.
import React, { Component } from 'react';
import { browserHistory } from 'react-router';
import { connect } from 'react-redux';
import { createDocument } from 'actions/documents';
#connect(null, { createDocument })
export default class Documents extends Component {
handleCreateClick () {
this.props.createDocument().then((action) => {
const { payload } = action;
browserHistory.push(`documents/${payload.id}`);
})
}
render () {
return (
<div>
<button onClick={this.handleCreateClick}>
Create
</button>
</div>
)
}
}
But again: this is not using the Redux state to handle errors, or anything. What would be the most "standard" way of handling such situation in Redux? I feel like putting the "new" id on the state would be overkill and way more boilerplate code.