How to render react component determined by string in TSX - reactjs

I want to achieve navigation based on hash change in url.
for example for url index.html#HomePage the app will load HomePage component.
import { HomePage } from '../components/homepage'
import { AnotherPage } from '../components/anoterpage'
export class NavigationFrame extends React.Component<any, State> {
constructor(props) {
super(props);
this.state = { pageName: this.pageNameFromUrl() };
}
onHashTagChanged = () => {
this.setState({pageName: this.pageNameFromUrl()});
}
public render() {
var Page = this.state.pageName as any;
return <Page /> //this renders <homepage /> when this.state.pageName = "HomePage";
}
}
is there any way how to dynamically create component based on string?

class CustomComponent extends React.Component{
render(){
return (
var DynamicComponent = this.props.component;
return <DynamicComponent />;
)
}
}
import it into your file and use like below,
return (
<CustomComponent component={this.state.pageName} />
);

Related

React JS - Pass Provider components methods to this.children

In React can methods be passed to {this.children} in a container consumer model. What I mean to ask is I have a provider component and I need to pass or refer the provider components methods in the child component.
export default class ContainerCompo extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
return (
{this.props.children}
}
}
export default class InputComponent extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
validate() {
ContainerCompo.methodOne(param)
}
render() {
return <InputComponent />
}
// Rendering the components
<ContainerCompo>
<InputComponent containerMethods={methods of ContainerCompo}/>
</ContainerCompo>
I hope my question is clear here, please suggest
First create a react context.
import React, { Component, createContext } from 'react';
// Create's authentication context to be use anywhere in the app
const ContainerContext = createContext();
export default ContainerContext;
Then create a provider for it.
export default class ContainerProvider extends Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
const { children } = this.props;
return (
<ContainerContext.Provider
value={{
container: {
methodOne: (...params) => this.methodOne(...params),
methodTwo: (...params) => this.methodTwo(...params)
}
}}
>
{children}
</ContainerContext.Provider>
)}}
Wrap your App with the provider.
import ContainerProvider from './ContainerProvider'
<ContainerProvider>
<App />
</ContainerProvider>
Then create a consumer for the context
export default function withContainer(InComponent) {
return function ContainerComponent(props) {
return (
<ContainerContext.Consumer>
{({ container }) => <InComponent {...props} container={container} />}
</ContainerContext.Consumer>
);
};
}
Then import the consumer and user in your components and you will get the methods as props
import withContainer from './ContainerConsumer'
render() {
const { container } = this.props;
return(<div />)
}
export default withContainer(YourComponent);

Modify react child components state for storybook

I have a react Component that I am trying to add to a storybook. It has child components that have component state which changes the way the component displays. I would like to set that component state to show in my storybook. What is the best way to achieve this ?
class ParentComponent extends PureComponent<ParentComponentProps> {
render() {
return (
<ChildComponent />
)
}
}
class ChildComponent extends PureComponent<ChildComponentProps> {
constructor(props) {
super(props);
this.handleOnBlur = this.handleOnBlur.bind(this);
this.state = {
isValid: true
};
}
handleOnBlur() {
this.setState({
isValid: isInputValid()
});
}
render() {
return (
<TextField
placeholder="eg. 12345"
validationMessage={'not a valid input'}
isInvalid={this.state.isValid}
onBlur={this.handleOnBlur}
/>
)
}
}
And Storybook code looks like this at the moment
import React from 'react';
import { Provider } from 'react-redux';
import ParentComponent from './ParentComponent';
export default { title: 'UpdateChildComponent' };
export const FieldValidationShowing = (state) => {
const { store, updateState } = mockStore;
updateState(state);
return (
<Provider store={store}>
<ParentComponent />
</Provider>
);
};
The above code is a sample of what I am doing.

Accessing variable from imported class from another React script

I'm importing a class from another script in my main React App, and would like to access a variable within that class from the main App. Basically the user types something into a textbox, then clicks a button to add that value to a variable. In the main App I import that class, then have another button to print those values (selectedvalues). I'm not entirely sure how to do it, but this is my code so far:
Class I am importing:
import React, { Component } from 'react';
class MyModule extends Component {
constructor() {
super();
this.state = {
selectedValues: '',
}
}
addValue() {
this.selectedValues += document.getElementById('textBox1').value + ', '
return this.selectedValues
}
render() {
return(
<div>
<input type='text' id='textBox1' />
<button onClick={() => this.addValue()}>Add Value</button>
</div>
)
}
}
export default MyModule
And where I would like to actually access that value
import React, { Component } from 'react';
import MyModule from './myModule.js'
class App extends Component {
constructor() {
super();
this.state = {
}
}
printValues() {
console.log(document.getElementById('themodule').selectedvalues)
}
render() {
return(
<MyModule id='themodule' />
<button onClick={() => printValues()}>Print values</button>
)
}
}
export default App
Is there a way I can do this?
Thanks!
Edit JS-fiddle here https://jsfiddle.net/xzehg1by/9/
You can create Refs and access state and methods from it. Something like this.
constructor() {
this.myRef = React.createRef();
}
render() { ... <MyModule id='themodule' ref={this.myRef} /> }
printValues() {
console.log(this.myRef)
}
more info here https://reactjs.org/docs/refs-and-the-dom.html
Basically, your state (selectedValues) has to go one level up in the React tree. You have to declare it as App's state, and then pass it down to MyModule via props.
Btw in addValue(), you're not changing any state. And this.selectedValues will be undefined. It's this.state.selectedValues, and this.props.selectedValues once you correct your code.
I think you should first read all react concepts and then start working on it. Anyhow i am modifying your code in one way to get your desired functionality but remember this is not best practice you have to use Redux for this kind of features
import React, { Component } from 'react';
class MyModule extends Component {
constructor() {
super(props);
this.state = {
inputValue : ''
};
this.handleInput = this.handleInput.bind(this);
this.addValue = this.addValue.bind(this)
}
handleInput(e){
this.setState({
inputValue : e.target.value
})
}
addValue() {
this.props.addValue(this.state.inputValue);
}
render() {
return(
<div>
<input type='text' id='textBox1' onChange={handleInput} />
<button onClick={this.addValue}>Add Value</button>
</div>
)
}
}
export default MyModule
and your main component should be
import React, { Component } from 'react';
import MyModule from './myModule.js'
class App extends Component {
constructor() {
super(props);
this.state = {
selectedValues : ''
};
this.printValues = this.printValues.bind(this);
this.addValues = this.addValues.bind(this);
}
printValues() {
console.log(this.state.selectedValues);
}
addValues(val){
this.setState({
selectedValues : this.state.selectedValues + " , "+val
})
}
render() {
return(
<React.Fragment>
<MyModule addValue={this.addValues}/>
<button onClick={this.printValues} >Print values</button>
</React.Fragment>
)
}
}
export default App
This should do your work

How to show a component randomly on every page load? (React)

How can I show a component randomly on every page load (using React)?
For example, I have two components:
<ComponentOne /> and <ComponentTwo />
I would like to randomly show one of the components on each page load.
Should I do it in componentDidMount()?
class MyComponent extends React.Component {
loadRandomComponent() {
// return <ComponentOne /> || <ComponentTwo />
}
componentDidMount() {
this.loadRandomComponent();
}
}
See if that helps
class ComponentThree extends React.Component {
render() {
return <div>ComponentThree</div>;
}
}
class ComponentTwo extends React.Component {
render() {
return <div>ComponentTwo</div>;
}
}
class ComponentOne extends React.Component {
render() {
return <div>ComponentOne</div>;
}
}
class Hello extends React.Component {
randomize(myArray) {
return myArray[Math.floor(Math.random() * myArray.length)];
}
render() {
var arr = [<ComponentOne />, <ComponentTwo />, <ComponentThree />]
return <div>Hello {this.randomize(arr)}</div>;
}
}

React propTypes errors not showing

I'm having problems with React propTyoes. I'v created a component that require 2 props to work as you guys can see in the code below.
When I use the component in the App file, passing just 1 prop, without the "stateSidebarVisible" it doesn't throw me any error/warning from react...
(I read a lot of things about the NODE_ENV production/development, I searched in my node for process.env and didnt found the NODE_ENV variable by the way).
Any clue?
FFMainHeader
export default class FFMainHeader extends React.Component {
render() {...}
}
FFMainHeader.propTypes = {
stateSidebarVisible: React.PropTypes.bool.isRequired,
handleSidebarChange: React.PropTypes.func.isRequired
};
App
This is where i call the FFMainHeader component.
export default class FFMainApp extends React.Component {
.......
render() {
return (
<div id="FFMainApp">
<FFMainHeader
handleSidebarChange={this.onSidebarChange} />
<FFMainSidebar />
</div>
);
}
}
EDIT
export default class FFMainHeader extends React.Component {
constructor(props) {
super(props);
this.clickSidebarChange = this.clickSidebarChange.bind(this);
}
clickSidebarChange(e) {
e.preventDefault();
(this.props.stateSidebarVisible) ?
this.props.stateSidebarVisible = false :
this.props.stateSidebarVisible = true;
this.props.handleSidebarChange(this.props.stateSidebarVisible);
}
render() {
return (
<header id="FFMainHeader">
<a href="#" onClick={this.clickSidebarChange}>
Abre/Fecha
</a>
</header>
);
}
}
FFMainHeader.propTypes = {
stateSidebarVisible: React.PropTypes.bool.isRequired,
handleSidebarChange: React.PropTypes.func.isRequired
};

Resources