call react component-element as variable - javascript

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 />;
}

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.

Use imported variable as a dinamic prop in React

Sorry for the noob question, but I'm a noob in React and I am strugling with this.
I have a file that exports a variable that is being mutated over time. Let's say something like this (not the real code, the variable is changing correctly):
// variable.js
let myVar = 0;
setInterval(() => myVar++, 3000);
export { myVar };
and a react component that has to display the current value:
import React, { Component, Fragment } from "react";
import { myVar } from './variable.js';
export default class myComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}
}
What would be the best approach to get the variable displayed correctly while they change? I have tryied to set is as a state, as a prop and rendering it directly, but I am missing something.
I can not export a getter function, as I don't know from the component when the variable is going to change, but maybe I can change the approach? maybe throwing an event in each change?
Try this, It won't work like the real-time update. But you can access like below
You can create a custom hook, that will update real-time
export default function useUpdate() {
const [myVar, setState] = useState(0)
setTimeout(function () {
setState(myVar++);
}, 3000);
return [myVar, setState];
}
import React, { Component, Fragment } from "react";
import { useUpdate } from './variable.js';
export default () => {
const [myVar] = useUpdate();
return (
<Fragment>
<div>{myVar}</div>
</Fragment>
);
}

React context between unrelated components

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>;
}

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?

Jest expected mock not called (redux component)

In React, I am testing that a button click inside a child component causes a function to be called in the parent component (onDeleteClick), via event bubbling.
For this test, I am using mount, as shallow will not allow us to trigger a function in a child component.
onDeleteClick, the function I am trying to check whether it was called or not, is a class property which in this case, is an arrow function.
I am mocking the onDeleteClick function, and passing it into my component via a Redux Provider when starting the test.
The problem I am having is that at the end of the test, when I perform a check to see if the mocked function was called, it returns 0.
expect(onDeleteClick.mock.calls.length).toBe(1);
If I put a console.log within onDeleteClick(), it's outputted during the test, so I know that the function is in fact being called.
I have researched this quite a bit and so far haven't gotten anything to work.
Some suggestions were to spy on my mocked function, and then call forceUpdate on the wrapper, but this didn't yield any positive results.
For this, I am using Jest with Enzyme.
Reference Code:
Parent.js
import { deleteAccount } from '../../actions/profileActions';
import ChildComponent from '../common/ChildComponent';
class ParentComponent extends Component {
onDeleteClick = () => {
console.log('onDeleteClick was executed during this test!')
this.props.deleteAccount();
}
render() {
let dashboardContent;
dashboardContent = (
<div>
<ChildComponent onDelete={this.onDeleteClick} />
</div>
);
return (
<div>
{dashboardContent}
</div>
);
}
}
// propTypes and mapStateToProps removed from this post
export default connect(
mapStateToProps,
{ deleteAccount }
)(ParentComponent);
__tests__/ParentComponent.js
import React from 'react';
import { mount } from 'enzyme';
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import ParentComponent from '../ParentComponent';
import thunk from "redux-thunk";
const mockStore = configureStore([thunk]);
const deleteAccount = jest.fn();
const props = {
deleteAccount
}
const randomTestState = {
// some initial state, not important
};
const randomTestStore = mockStore(randomTestState);
describe('<ParentComponent />', () => {
it(`mounts the ParentComponent component and, when ChildComponent sends onDelete, then deleteAccount function is called once`, () => {
const wrapper = mount(
<Provider store={randomTestStore} props={props}>
<Router >
<ParentComponent />
</Router>
</Provider>
);
// Here, I grab an element in ChildComponent and simulate a click using Enzyme, then the event bubbles up, and deleteAccount() is called in the parent component.
// the console.log we expect to see from onDeleteClick is logged to console.
// the call does not seem to have registered though and the expect returns falsy
expect(deleteAccount.mock.calls.length).toBe(1);
})
});
Could the problem be that I am wrapping the component in a Provider?
I have a hunch, but I couldn't find any concrete examples of tests which use a Provider to wrap their component when running integration testing
The solution was that I needed to change my main ParentComponent file from
class ParentComponent extends Component {
to this:
extend class ParentComponent extends Component {
and then in my test file, import the component like so:
import { ParentComponent } from '../ParentComponent'; // non-default export should be wrapped in braces
and then update my test so that I assign the wrapper variable like so:
const wrapper = mount(<ParentComponent {...props} />);
This then allowed the test to pass
expect(deleteAccount.mock.calls.length).toBe(1);
It was recommended here in the Redux docs

Categories

Resources