Select Inner component in a React Component - javascript

im trying to do a Main component (in the example, Container), which can hold a inner component selectable, in the example is harcoded (the condition is set to true).
I need the inner component extends from React.Component, i cant use it like a function: const ChildOne = (.... )
There're 2 child component, the idea is to use more of them.
But, i can't, i got error when rendering the inner component:
Functions are not valid as a React child. This may happen if you
return a Component instead of from render. Or maybe you
meant to call this function rather than return it.
class ChildOne extends React.Component {
render() {
return (
<div>
<p> Child One </p>
</div>
)
}
}
class ChildTwo extends React.Component {
render() {
return (
<div>
<p>Child Two</p>
</div>
)
}
}
class Container extends React.Component {
render() {
let condition = true; //Just for testing purpose
let comp = null;
if (condition)
comp = ChildOne;
else
comp = ChildTwo;
return (
<main>
{comp}
</main>
)
}
}
class App extends React.Component {
render() {
return (
<div>
<div><Container /></div>
</div>
)
}
}
https://jsfiddle.net/01L8amgs/
I ran out of ideas... thanks in advance.

You should use capitalized letter, to assign a React custom component to a variable. Like Comp = ChildOne; or Comp = ChildTwo.. then just do <Comp />
From User-Defined Components Must Be Capitalized :
When an element type starts with a lowercase letter, it refers to a
built-in component like or and results in a string 'div'
or 'span' passed to React.createElement. Types that start with a
capital letter like compile to React.createElement(Foo) and
correspond to a component defined or imported in your JavaScript file.
We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a
capitalized variable before using it in JSX.
class ChildOne extends React.Component {
render() {
return (
<div>
<p> Child One </p>
</div>
);
}
}
class ChildTwo extends React.Component {
render() {
return (
<div>
<p>Child Two</p>
</div>
);
}
}
class Container extends React.Component {
render() {
let condition = true; //Just for testing purpose
let Comp = null;
if (condition) Comp = ChildOne;
else Comp = ChildTwo;
return (
<main>
<Comp />
</main>
);
}
}
class App extends React.Component {
render() {
return (
<div>
<div>
<Container />
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

You need to render components with the proper syntax: <Comp> instead of {comp}
Here is a working example: https://jsfiddle.net/01L8amgs/2/
Notice the Container class render function changed for this
class Container extends React.Component {
render() {
let condition = false;
let Comp = null; <===== Uppercased variable name
if (condition)
Comp = ChildOne;
else
Comp = ChildTwo;
return (
<nain>
<Comp /> <===== Render as component
</nain>
)
}
}

Related

How to properly create and render functional components?

I am attempting to create and render a functional component using the instructions here as a base. From what I've sen in there I should be able to do something along the lines of:
class MyComponent extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
)}
function OtherComponent(props) {
return (
<div>
test
</div>
);
}
}
But this throws the error:
Unexpected token: function OtherComponent(props) {
^
I found a few posts that suggested removing the function so I tried that but then it throws the error:
OtherComponent is not defined
I'm able to get it working by creating a separate class component like so:
class OtherComponent extends React.Component {
render() {
But that's not what I want to do. What is the proper way to create/render a functional component in React.js?
For example this one works. See the docs ;)
React - Composing Components
function OtherComponent(props) {
return <div>test</div>;
}
class App extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
);
}
}
Try this
class MyComponent extends React.Component {
OtherComponent = (props) => {
return (
<div>
test
</div>
);
}
render() {
return (
<div>
{this.OtherComponent("test")}
</div>
)}
}
You can't define a component inside of another component. A functional component means that the component is created from a function and is not a class. It can't have it's own state, because the state is initialized in class constructor. Check out this article for more info https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc
const otherComponent = (props) =>
<div>
test
</div>;
Here is another way. Its not correct to declare a component in a render function. If it is used solely in a parent component why not make that explicit and use static
class MyComponent extends React.Component {
static myOtherComponent = (props) => <div>{'test'}</div>
render(){
return(
<div>
<MyComponent.myOtherComponent {props} />
</div>
)
}
The myOtherComponent behaviour is controlled purely through the props it gets , it won't have its own state.
Or you could just make it a separate component e.g
export default myOtherComponent = (props) => ()
and import it into MyComponent. Please note , now with hooks ( see React Docs ), you can use hooks to mimic state etc in functional components and the latter approach might be your cleanest and most flexible approach.
This way you can define a function component
function OtherComponent(props) {
return <div>{props}</div>;
}
And now you can use functional component in your App (class component) like below
class App extends React.Component {
render() {
return (
<div>
<OtherComponent props="test" />
</div>
);
}
}

Relation between components

I have two stateful components:Grid and Item.Item is rendering by Grid and have props which reference to method (handler) defined in Grid <Item example={this.props.inGridHandler} />
Ok. But what if I have third stateful component let's name it Handy and I want that inGridHandler is defined not in Grid component as before but in Handy. How to achieve this with preserving all this structure ?
class Grid extends Component{
ingridHandler=()=>{
console.log('I want to be defined in Handy Component, not here');
}
Render(){
Return(
`<Item example={this.inGridHandler} />`
);
}
};
export default Grid;
class Handy extends Component{
inGridHandlerWantToBeDefinedHere=()=>{
console.log("I want to be defined here and pass to Grid component as props of Item component which is rendered there'
}
render(){
return(
)
}
}
Here is what you want if I understand you right. This is a very simple process. You are just passing the props all the way down. But, as I try to explain in my comments in the future you should think better approaches if you don't want to pass the props like this.
class Handy extends React.Component {
inGridHandler = () => {
console.log("ingridhandler");
};
render() {
return <Grid inGridHandler={this.inGridHandler} />;
}
}
class Grid extends React.Component {
render() {
return <Item inGridHandler={this.props.inGridHandler} />;
}
}
const Item = props => (
<button onClick={props.inGridHandler}>Click me and look the console.</button>
);
ReactDOM.render(
<Handy />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

React include dynamic prop value in component name

I am trying to render a react component. The first part of the component will remain the same, however the second part needs to change dynamically based on the data returned from the props. Is there some way to concatenate these together?
import * as Icon from 'react-cryptocoins';
class ResultRow extends PureComponent {
render() {
return (
<div className="component-result-row">
<Icon.{this.props.name}/>
</div>
);}}
Hardcoding the name works as expected
<{Icon.image1}/>
Solution:
import * as Icon from 'react-cryptocoins';
class ResultRow extends PureComponent {
var name = this.props.name;
var Component = Icon[symbol];
render() {
return (
<div className="component-result-row">
<Component/>
</div>
);}}
One possible way is store the value in a variable (should start with capital letter) then render that.
Like this:
class ResultRow extends PureComponent {
render() {
const Comp = Icon[this.props.name];
return (
<div className="component-result-row">
<Comp />
</div>
);
}}

ReactJs: Dynamic component loading passing properties

I have a library of ReactJS components, as the following code:
components.js
class Comp1 extends Component {
render () {
return (
<div>Component 1 Text: {this.props.text}</div>
);
}
}
class Comp2 extends Component {
render () {
return (
<div>Component 2 Text: {this.props.text}</div>
);
}
}
export components = {
Comp1,
Comp2
}
The main component needs to choose wich one to render based on a passed property:
main.js
import { components } from './components';
class Main extends Component {
getComponent = (name) => {
return components[name];
};
render () {
let comp = this.getComponent(this.props.componentName);
return (
<div>
<comp <=== HOW TO CALL THE GIVEN COMPONENT PASSING ITS PROPERTY
text={'This is component' + this.props.componentName }
/>
</div>
);
}
}
class App extends Component {
render () {
return (
<div>
<Main componentName='Comp1' /> // Or 'Comp2'
</div>
);
}
}
}
I need in the main code to render the component and pass its properties, but I can´t make it work (see the comments on code). A simple {comp} renders the component, but I need to be able to pass its properties accordingly.
What I´ve tried:
{comp text={'This is component' + this.props.componentName}}
<comp text={'This is component' + this.props.componentName}/>
None of them worked.
You component name need to begin with a UpperCase character. so it should look like
import { components } from './components';
class Main extends Component {
getComponent = (name) => {
return components[name];
};
render () {
let Comp = this.getComponent(this.props.componentName);
return (
<div>
<Comp text={'This is component' + this.props.componentName }
/>
</div>
);
}
}
class App extends Component {
render () {
return (
<div>
<Main componentName='Comp1' /> // Or 'Comp2'
</div>
);
}
}
}

How to modify react extended class?

So let's say I have this
class ExampleOne extends ExampleTwo
and in ExampleTwo has this
return (
<div className="test">
<MyComponent exampleLabel="ExampleTwo">
Is it possible to modify MyComponent's exampleLabel to say "ExampleOne" for class ExampleOne?
There are two scenarios
1) If you can modify ExampleTwo, use react props
class ExampleTwo extends React.Component {
render() {
return <div>
<MyComponent exampleLabel={this.props.exampleLabel || 'ExampleTwo'}/>
</div>;
}
}
// And render as
<ExampleOne exampleLabel="ExampleOne"/>
2) If you can't modify ExampleTwo, then you can override render function
class ExampleOne extends ExampleTwo {
render() {
return <div>
<MyComponent exampleLabel="ExampleOne"/>
</div>;
}
}
Yes, Extending ExampleOne is fine, you would just pass it as a prop like so:
In ExampleTwo:
return (
<div className="test">
<MyComponent exampleLabel="ExampleOne">

Categories

Resources