How to pass functions to different components react - reactjs

Sorry for the noob question in advance. I have got a button, and I have a function in a different folder which I am trying to execute... I have tried to import the function from my other folder however it does not seem to be exceuting...How do I call this correctly?
ModalTopBar.js
import LineageContent from '../../ReusableComponents/Lineage/LineageContent'
<Button text='Get SQL' onClick={LineageContent.onHandle} />
LineageContent:
const onHandle = () => {
console.log('clicked')
}
File path to where I am importing lineage content if it helps:

First of all lets clear that the Components in reactjs is reusable so you can't simply import a new instance then use a nested function from this component
if the Component that you want to use a nested function is parent or even ancestor to the current component then you should props and pass the function address throw it
else you should use something like redux and save this function address in a store then use wherever you want this is a bad practice to use redux

Related

Where to store instance of API object in react (next.js) app?

I'm trying to build react (with next.js) based chat client using the LiveChat CustomerSDK API.
I currently use a useEffect hook to initialize and then store the object with a useState hook.
const [customerSDK, setCustomerSDK] = useState();
useEffect(() => {
const sdk = CustomerSDK.init(config);
setCustomerSDK(sdk)
}, []);
But I am wondering whether useState is the best way for the customerSDK object, since it doesn't need to trigger a re-render. Therefore I also considered using useRef instead or maybe just storing it in the window object. But neither "feels right".
I have to consider that I need to access the customerSDK object to set the listeners (e.g. customerSDK.on('connected', ...) and also for example sending messages (customerSDK.sendEvent(...)
Is there a recommended/preferred way to approach a situation like this?
Theres another option if you know you only have 1 project accessing it, simply put it in a file and export it, then import this everywhere you need it. If it needs no context (i.e. react state) from your components, why have it stored in a component at all?
const sdk = CustomerSDK.init(config);
export default sdk
Then import that where you need it. It will act as a singleton.

How to initialize and use context in the same component?

I have a context called SortContext. What I would like to do is initialize this context (create its provider) and then use that context in the same component. Is this possible?
For example:
export default function MyComponent ({children}) {
const mySortValue = useContext(SortContext)
return (
<SortContext.Provider value={'exampleValue'}>
{children}
</SortContext.Provider>
)
}
In this component, the variable mySortContext will not have access to the value 'exampleValue', as this context is not created until after the useContext hook.
Alternatively:
export default function MyComponent ({children}) {
return (
<SortContext.Provider value={'exampleValue'}>
<SortContext.Consumer>
{context => {
const mySortValue = useContext(SortContext)
return children
}}
</SortContext.Consumer>
</SortContext.Provider>
)
}
Something like this doesnt work, as the function cannot use react hooks.
I could obviously just create a new component, put it within the <SortContext.Provider> tags, and access the context there, but is there any way to do it all in one component?
//Sidenote
To give some background on why I want this, I use the context to establish some information about how data should be sorted. I would like any components within the context to have access to this data. In the case where I want a simple button, list of data, and sort function in a single component, it seems like overkill to create two components; one to feed it the sort context, the other to host the sort buttons and data.
This is not possible without creating another component.
This is mentioned in the "Pitfall" box in the react js beta docs here (scroll down a bit) :
https://beta.reactjs.org/apis/usecontext#passing-data-deeply-into-the-tree
What I would like to do is initialize this context (create its provider) and then use that context in the same component. Is this possible?
In a sense, yes, but you'd do it through local variables, not context.
You're already writing code to generate the value that you'll pass into the provider. In your example, that's just value={'exampleValue'}, but even in a more complicated realworld case, it's entirely under your control what value you pass in. Simply save that value in a local variable, and use it anywhere else you need it.
export default function MyComponent ({children}) {
// Replace the following with whatever complicated logic you need to generate the value
const mySortValue = 'exampleValue';
// Do stuff with mySortValue here
return (
<SortContext.Provider value={mySortValue}>
{children}
</SortContext.Provider>
)
}

React.forwardRef is already possible without it, so what's the use of it?

I'm confused on the point of React.forwardRef. As explained in its documentation, I understand that its main use is for a Parent Component to gain access to DOM elements of the Child Component. But I can already do that without even having to use it.
Here is a code example that you can plug into CodeSandbox and see that it works:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Or here's the embed of this example. Honestly, I'm kind of new to this and I don't know exactly how embeds work and whether someone fiddling with the embed changes my original Sandbox or not, so I was hesitant to put it. But here it is.
Example Forwarding Ref
In the example, the parent App() component successfully passes a ref to the child which the child attaches to its rendered div. After it renders, it calls a callback function to the parent. The parent then does a console log where it proves that its forwarded ref now has a hold of the child's div. And this is all done without React.forwardRef.
So what then is the use for React.forwardRef?
You're absolutely right that you can do what you've described. The downside is that you're forced to expose an API (ie: the fRef prop) for it to work. Not a huge deal if you're a solo developer building an app, but it can be more problematic eg. if you're maintaining an open-source library with a public API.
In that case, consumers of the library won't have access to the internals of a component, meaning you'd have to expose it for them somehow. You could simply do what you're suggesting in your example and add a named prop. In fact, that's what libraries did before React 16.3. Not a huge deal, but you'd have to document it so people know how to use it. Ideally, you'd also want some kind of standard that everyone used so it wasn't confusing (many libraries used the innerRef naming convention), but there'd have to be some consensus around that. So all doable, but perhaps not the ideal solution.
Using forwardRef, passing a ref to a component just works as expected. The ref prop is already standardized in React, so you don't need to go look at docs to figure out how to pass the ref down or how it works. However, the approach you describe is totally fine and if it meets your needs, by all means go with that.
As mentioned in the docs , it's useful for highly reusable components, meaning components that tend to be used like regular HTML DOM elements.
This is useful for component libraries where you have lots of "leaf" components. You've probably used one like Material UI.
Example:
Let's say you're maintaining a component library.
You create a <Button/> and <Input/> component that maybe just adds some default styling.
Notice how these components literally are just like regular HTML DOM elements with extra steps.
If these components were made to be used like regular HTML DOM elements, then I expect all the props to be the same, including ref, no?
Wouldn't it be tedious if to get the button ref from your <Button/> component I'd have to get it through something like fRef or buttonRef ?
Same with your <Input/>, do I have to go to the documentation just to find out what ref to use and it's something like inputRef ? Now I have to memorize?
Getting the ref should be as simple as <Button ref={}/>
Problem
As you might know, ref will not get passed through props because, like key, it is handled differently by React.
Solution
React.forwardRef() solves this so I can use <Button ref={}/> or <Input ref={}/>.

How to import a component or file in React using variables?

I'm building a web app using React that shows the blueprint for the building you select, in an already selected campus.
I have a "Content" component that loads the campus or building map, depending what you chose.
The "BuildingMap" component needs to load a specific blueprint according to what building you selected. It gets the props.building with the name of the building but I don't know how to load a component using that variable.
I have tried import, fetch and require but nothing seems to work.
Please help.
My code looks something like this:
//Content Component
<BuildingMap building={selectedBuilding} campus={selectedCampus} />
//BuildingMap Component
import *MyBlueprint* from (specific folder depending on the campus selected)
class BuildingMap extends React.Component {
render(){
return (
<div className="blueprint" id={this.props.building}>
{*MyBlueprint*}
</div>
)
}
}
Unfortunately, you cannot import/require components dynamically in React environment.
Depending on how many buildings/blueprints there are, it's possible to import them one by one, create component-building map and pick component by building ID.
If there are many/infinite components to load, I would surely pick another method - don't know content of your problem.
import BlueprintA from './BlueprintA'
import BlueprintB from './BlueprintB'
import BlueprintC from './BlueprintC'
// ...
class BuildingMap extends React.Component {
render(){
const C = {
buildingA: BlueprintA,
buildingB: BlueprintB,
buildingC: BlueprintC,
// ...
}[this.props.building]
return (
<div className="blueprint" id={this.props.building}>
<C />
</div>
)
}
}
This question is pretty old but as I was looking for how to solve the same problem let me give my answer. It can be done with dynamic import React.lazy:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
See more details here: https://reactjs.org/docs/code-splitting.html#reactlazy
To add to #Andreyco's answer:
Using a lookup table of string IDs/names to component classes is a typical React idiom. One common use case is a modal manager component that can render multiple different types of modals. For some examples, see Dan Abramov's answer at "How can I render a modal dialog in Redux?" (not Redux-specific), as well as some of the related articles in the React Component Patterns#Modal Dialogs and Redux Techniques#UI sections of my React/Redux links list.
Per #azium's comment: it is definitely possible to use dynamic importing (via require.ensure() or the new import() function) to load chunks at runtime, and you could add the exports from those dynamically imported chunks into a lookup table when they are loaded.

Multiple stores with Alt (Flux)

The example on the main Alt page shows how to connect a single store to a React component using #connectToStores.
I wonder if we can still use #connectToStores to connect 2 stores to a React component. I suppose the getStores method will be like this:
static getStores() {
return [TodoStore, TodoStore2];
}
but I don't know how the getPropsFromStores should be.
This question is answered here
https://github.com/goatslacker/alt/issues/420
If you want to connect 2 stores together for one component, wrap your component in an AltContainer and then reference the props the AltContainer passes to your component.

Resources