React context between unrelated components - javascript

For learning purposes I'm just trying to render this dumb example where Component A has a variable that creates a random number and another (unrelated) Component B can render it with useContext. I don't know how to make the provider of the context to know that the value is the variable from Component A.
I created another file to do the React.createContext()... but still don't know how to make the random number to reach there or the App Component to do the Provider. I know I could create the random number in App component and provide whatever component I want with that value, but I just want the value to be generated in Component A and reach Component B. Any ideas? Maybe its so simple I can't see it.
What I have at the moment:
Component A:
import React from'react';
export default function RandomNumGenerator() {
const randomNum = Math.random();
return(
<h2>Your random number is:</h2>
)
}
Component B:
import React from'react';
export default function RandomNumRenderizator() {
return(
<h2></h2> //Want to render the random num here
)
}
App Component:
import React from 'react';
import RandomNumGenerator from "./FunctionalComponents/RandomNumGenerator/RandomNumGenerator";
import RandomNumRenderizator from "./FunctionalComponents/RandomNumRenderizator/RandomNumRenderizator";
import RandomNumContext from "./contexts/RandomNumContext";
export default function App() {
return (
<div>
<RandomNumGenerator/>
<RandomNumContext.Provider value={}> //Empty value as I don't know what to send
<RandomNumRenderizator/>
</RandomNumContext.Provider>
</div>
);
}
And the Context:
import React from "react";
const RandomNumContext = React.createContext(); //Don't know if there should be anything as defaultValue
export default RandomNumContext;

As data flows down in React, the value you wish to pass have to be in scope with the context provider, then you just need to read the context value using a hook:
export default function App() {
const randomNum = Math.random();
return (
<>
<RandomNumDisplay num={randomNum} />
<RandomNumContext.Provider value={randomNum}>
<RandomNumRenderizator />
</RandomNumContext.Provider>
</>
);
}
export default function RandomNumRenderizator() {
const randomNum = useContext(RandomNumContext);
return <h2>{randomNum}</h2>;
}

Related

Problem when pass data in ReactJS with props and state

I have the problem when I try to pass the props through the function component .In parent component I have a state of currentRow with return an array with object inside, and I pass it to child component. It return a new object with an array inside it. What can I do to avoid it and receive exact my currentRow array.
there is example of the way I do it
Parent component
import React, { useState } from "react";
import ToolBar from "./Toolbar";
function Manage() {
const [currentRow, setCurrentRow] = useState();
console.log("from manage", currentRow);
return (
<div>
<ToolBar currentRow={currentRow} />
</div>
);
}
export default Manage;
Child Componet
import React from 'react'
function ToolBar(currentRow) {
console.log("from toolbar", currentRow);
return(
<div></div>
);
}
export default ToolBar
And this is my Log
enter image description here
Try accessing it like below:
import React from 'react'
function ToolBar({currentRow}) {
console.log("from toolbar", currentRow);
return(
<div></div>
);
}
export default ToolBar
A React component's props is always an object. The reason for this is that otherwise it would be impossible to access the properties of a component which received multiple props.
example:
<SomeComponent prop1={prop1} prop2={prop2} />
---
const SomeComponent = (props) => {
console.log(props.prop1);
console.log(props.prop2);
}
So in order to resolve your issue, you could destructure the props object in your ToolBar component like this:
const ToolBar = ({ currentRows }) => {
...
}
Just keep in mind that a component will always receive its props as an object. There is no way to change that as of right now.

call react component-element as variable

Is it possible to call a React component element with a variable inside?
import React from "react"
/*React functional component*/
function someName() {
const someVar = "componentName"; //the name of the called component
return(
<{someVar}/>
)
}
export default someName;
I try to implement this in a router and to change the filenames(Sites) (in the element) dynamically with useState from fetched data.
I am open to all kind of help :)
There is no direct way to do that but you can use this approach.
import ComponentA from '...path';
import ComponentB from '...path';
...
const components = {
componentA: ComponentA,
componentB: ComponentB,
...
}
...
function App(props) {
const TargetComponent = components[props.componentName];
return <TargetComponent />;
}

How to provide and consume context in the same component?

I'm using react context api for my game app and I created a GameContext.js
import React, { useState, createContext } from 'react';
const GameContext = createContext();
const GameProvider = ({ children }) => {
const [startgame, setStartgame] = useState(false);
return (
<GameContext.Provider value={[startgame, setStartgame]}>
{children}
</GameContext.Provider>
);
};
export { GameContext, GameProvider };
And in the App.js I provide the context.
import { GameProvider, GameContext } from './context/GameContext';
const App = () => {
console.log(useContext(GameContext), 'Gamecontext');
return (
<GameProvider>
<div className="App">
{!startgame ? <WelcomeScreen />
: <GameScreen />}
</div>
</GameProvider>
);
};
export default App;
This doesnt work because startgame is not accessible in App.js.
Also, I noticed the useContext(GameContext) is undefined. I want to use the startgame value in App.js, but I cant destructure an undefined value.
How can one provide and consume the context in the same component App.js? Is this the right way or am missing something?
You need to use Context.Consumer component instead of useContext hook. Because when you provide a context, it will be consumable via useContext hook or this.context only within its children not parent. In that case you need to use MyContext.Consumer component.
import { GameProvider, GameContext } from './context/GameContext';
const App = () => {
return (
<GameProvider>
<div className="App">
<GameContext.Consumer>
{(ctx) => (!ctx.startgame ? <WelcomeScreen /> : <GameScreen />)}
</GameContext.Consumer>
</div>
</GameProvider>
);
};
export default App;
From React docs:
Consumer - Requires a function as a child. The function receives the current context value and returns a React node. The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value argument will be equal to the defaultValue that was passed to createContext().

Accessing React component state from MDX

Assume that I have the following files.
import React, { useState } from 'react';
import someComputation from './someComputation';
type ComponentType = {
input: number;
};
const Component = (props: ComponentType) => {
const [state, setState] = useState(someComputation(props.input));
console.log(state.color); // "#440000" for example
return <>...some component UI</>;
};
export default Component;
import Component from "./Component"
# Title
## Header
Body text like this
<Component input={5} />
I want to refer to the {state.color} of the component above. How?
I think one way could be update the global or a context with the value of state and then create another component that just fetch the context value.
Is there a better (easier) way to achieve this?

Understanding React Higher-Order Components

Can someone please explain Higher-order components in React. I have read and re-read the documentation but cannot seem to get a better understanding. According to the documentation, HOCs help remove duplication by creating a primary function that returns a react component, by passing arguments to that function.
I have a few questions on that.
If HOCs create a new enhanced component, can it be possible not to pass in any component as argument at all?
In an example such as this, which is the higher order component, the Button or the EnhancedButton.
I tried creating one HOC like this:
// createSetup.js
import React from 'react';
export default function createSetup(options) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.testFunction = this.testFunction.bind(this);
}
testFunction() {
console.log("This is a test function");
}
render() {
return <p>{options.name}</p>
}
}
}
// main.js
import React from 'react';
import {render} from 'react-dom';
import createSetup from './createSetup';
render((<div>{() => createSetup({name: 'name'})}</div>),
document.getElementById('root'););
Running this does not show the HOC, only the div
Can anyone help out with a better example than the ones given?
A HOC is a function that takes a Component as one of its parameters and enhances that component in some way.
If HOCs create a new enhanced component, can it be possible not to pass in any component as argument at all?
Nope, then it wouldn't be a HOC, because one of the conditions is that they take a component as one of the arguments and they return a new Component that has some added functionality.
In an example such as this, which is the higher order component, the Button or the EnhancedButton.
EnhanceButton is the HOC and FinalButton is the enhanced component.
I tried creating one HOC like this: ... Running this does not show the HOC, only the div
That's because your createSetup function is not a HOC... It's a function that returns a component, yes, but it does not take a component as an argument in order to enhance it.
Let's see an example of a basic HOC:
const renderWhen = (condition, Component) =>
props => condition(props)
? <Component {...props} />
: null
);
And you could use it like this:
const EnhancedLink = renderWhen(({invisible}) => !invisible, 'a');
Now your EnhancedLink will be like a a component but if you pass the property invisible set to true it won't render... So we have enhanced the default behaviour of the a component and you could do that with any other component.
In many cases HOC functions are curried and the Component arg goes last... Like this:
const renderWhen = condition => Component =>
props => condition(props)
? <Component {...props} />
: null
);
Like the connect function of react-redux... That makes composition easier. Have a look at recompose.
In short, If you assume functions are analogues to Components, Closure is analogous to HOC.
Try your createSetup.js with:
const createSetup = options => <p>{options.name}</p>;
and your main.js
const comp = createSetup({ name: 'name' });
render((<div>{comp}</div>),
document.getElementById('root'));
A higher-order component (HOC) is an advanced technique in React for reusing component logic. Concretely, a higher-order component is a function that takes a component and returns a new component.
A HOC is a pure function with zero side-effects.
Example: CONDITIONALLY RENDER COMPONENTS
Suppose we have a component that needs to be rendered only when a user is authenticated — it is a protected component. We can create a HOC named WithAuth() to wrap that protected component, and then do a check in the HOC that will render only that particular component if the user has been authenticated.
A basic withAuth() HOC, according to the example above, can be written as follows:
// withAuth.js
import React from "react";
export function withAuth(Component) {
return class AuthenticatedComponent extends React.Component {
isAuthenticated() {
return this.props.isAuthenticated;
}
/**
* Render
*/
render() {
const loginErrorMessage = (
<div>
Please login in order to view this part of the application.
</div>
);
return (
<div>
{ this.isAuthenticated === true ? <Component {...this.props} /> : loginErrorMessage }
</div>
);
}
};
}
export default withAuth;
The code above is a HOC named withAuth. It basically takes a component and returns a new component, named AuthenticatedComponent, that checks whether the user is authenticated. If the user is not authenticated, it returns the loginErrorMessage component; if the user is authenticated, it returns the wrapped component.
Note: this.props.isAuthenticated has to be set from your application’s
logic. (Or else use react-redux to retrieve it from the global state.)
To make use of our HOC in a protected component, we’d use it like so:
// MyProtectedComponent.js
import React from "react";
import {withAuth} from "./withAuth.js";
export class MyProectedComponent extends React.Component {
/**
* Render
*/
render() {
return (
<div>
This is only viewable by authenticated users.
</div>
);
}
}
// Now wrap MyPrivateComponent with the requireAuthentication function
export default withAuth(MyPrivateComponent);
Here, we create a component that is viewable only by users who are authenticated. We wrap that component in our withAuth HOC to protect the component from users who are not authenticated.
Source
// HIGHER ORDER COMPOENTS IN REACT
// Higher order components are JavaScript functions used for adding
// additional functionalities to the existing component.
// file 1: hoc.js (will write our higher order component logic) -- code start -->
const messageCheckHOC = (OriginalComponent) => {
// OriginalComponent is component passed to HOC
const NewComponent = (props) => {
// business logic of HOC
if (!props.isAllowedToView) {
return <b> Not Allowed To View The MSG </b>;
}
// here we can pass the props to component
return <OriginalComponent {...props} />;
};
// returning new Component with updated Props and UI
return NewComponent;
};
export default messageCheckHOC;
// file 1: hoc.js -- code end -->
// file 2: message.js -- code start -->
// this is the basic component we are wrapping with HOC
// to check the permission isAllowedToView msg if not display fallback UI
import messageCheckHOC from "./hoc";
const MSG = ({ name, msg }) => {
return (
<h3>
{name} - {msg}
</h3>
);
};
export default messageCheckHOC(MSG);
// file 2: message.js -- code end -->
// file 3 : App.js -- code start --->
import MSG from "./message.js";
export default function App() {
return (
<div className="App">
<h3>HOC COMPONENTS </h3>
<MSG name="Mac" msg="Heyy !!! " isAllowedToView={true} />
<MSG name="Robin" msg="Hello ! " isAllowedToView={true} />
<MSG name="Eyann" msg="How are you" isAllowedToView={false} />
</div>
);
}
// file 3 : App.js -- code end --->

Categories

Resources