Im not able to create a React component dynamically.
I see blank page with no errors with below code.
1) Trying to create an element named "PieChart"
2) Below are the Two errors im seeing in console.
1. Warning: <PieChart /> is using incorrect casing. Use PascalCase for
React components, or lowercase for HTML elements.
2. Warning: The tag <PieChart/> is unrecognized in this browser. If you
meant to render a React component, start its name with an
uppercase letter.
3) Im Already using Pascal case "PieChart"
import PieChart from "../component/PieChart";
class App extends Component {
render() {
const GraphWidget = React.createElement("PieChart");
return (
<div>
{GraphWidget}
</div>
)
}
}
export default App;
From the createElement documentation:
Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type.
You are trying to use a React component type therefore you cannot use a string, you need to use the class directly:
const GraphWidget = React.createElement(PieChart);
If your aim is to map strings to components, you can create simple mapping using a dictionary:
const components = {
PieChart: PieChart
...
};
const GraphWidget = React.createElement(components['PieChart']);
You should user **PascalCase** Naming conventions.
For Example,
class StudentGrades extends Component{
// Your Stuff
}
the component you created should start with Capital latter and using
this within JSX also written with the same name
class TodoItem extends React.Component {
render(){
return <TodoItem>
}
this could be the one of the issue
Related
I wrote a component Foo in React.js (its parameter "interface" consists of a single parameter text; there are more parameters in my real code):
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props);
}
render(){
return <div>{this.props.text}</div>;
}
}
and I thought I could improve the code by modifying the property access as:
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props)
this._text = props.text
}
render(){
return <div>{this._text}</div>;
}
}
This would give me the benefits that
I can immediately see what properties are supported by having a look at the constructor.
The code that applies the properties gets shorter/better to read.
However, this destroys the update workflow for the property. In a parent component I use Foo like
<Foo text={this.state.parentText}/>
and
this.setState({parentText: "new text"})
does not trigger an update of the text in Foo any more. The constructor of Foo is only called once and therefore, the private variable this._text is not updated on property changes.
=> Using extra private properties to modify the parameter access turned out to be a bad idea.
=> What would you recommend to have a clear interface for the component without breaking the update workflow?
Some ideas:
a) List all used properties at the start of render (and componentDidUpdate)
render(){
const text = this.props.text;
return <div>{text}</div>;
}
b) Create a getter for each property and put them directly under the constructor, for example
get _text(){
return this.props.text;
}
c) (Only for shorter access.) Try to avoid class components. With function components there is direct access with props.text instead of this.props.text. Or, as a workaround, inherit from a custom component class that passes props argument to render:
render_props(props){
...
}
(Why doesn't react pass this.props as an argument to render by default?)
d) Document the supported properties in a doc string
=> If you know a better option / some standard / best practice, please let me know.
Also tried but failed:
I tried to use state in the child component, with the hope that it would be automatically updated on updates of the parent state:
import React from 'react';
export default class Foo extends React.Component {
constructor(props){
super(props)
this.state = {
text: props.text
}
}
render(){
return <div>{this.state.text}</div>;
}
}
However, this also breaks the update workflow. Using this.state only seems to make sense in the parent component.
Related:
Can I update a component's props in React.js?
https://github.com/vasanthk/react-bits/blob/master/anti-patterns/01.props-in-initial-state.md
Related topic:
How to interact with third party libraries using function components?
https://reactjs.org/docs/integrating-with-other-libraries.html
How do I use/include third party libraries in react?
Integrating React with Other Libraries
Use function components for React >= 16.8, also see recommendation at
https://www.w3schools.com/react/react_class.asp
Use useState hooks instead of setState. This is the modern way to write React, and gives you a simpler way to access state (foo.text, foo.setText). https://reactjs.org/docs/hooks-state.html
Typescript would help with docs (type props = { text: string }), but I also would like the answer for d) (your question is several questions I think).
Use props.text directly, instead of using extra shortcut variable const text = props.text suggested by option a). This way, you don't have a list of all available properties on top of the component function. However, using a consistent props. prefix makes it easier to spot the injected variables in the react code. If there is a huge number of properties and its hard to identify them, try to improve modularization.
JavaScript example code:
Child component Foo:
import React from 'react';
export default function Foo(props){
return <div>{props.text}</div>;
}
}
Parent component:
import React, { useState } from 'react';
import Froo from './foo';
export default function Parent(){
const [parentText, setParentText] = useState('Hello world');
return <Foo text={parentText}/>;
}
So I have a project where I have some react components that look like this (all in the same file List.js):
export default class List extends Component {
render(){//stuff}
}
List.Item = (props, context) => {
//function component stuff
}
Basically there's a react function component as a key of another react component if that makes sense. This is something I can't change, it's part of a library I am using. I'm trying to define a index.d.ts for this library, but when I try to define "List" like so:
//in index.d.ts
export as namespace myLibrary
export declare class List extends React.Component<any, any> {
Item: React.FunctionComponent<any>
}
how in the world do I add List.Item as an attribute of the type "list"?? I have tried overriding it by defining a second class/interface that extends the first, tried using a constructor to assign it to 'this', and tried the above, but none did the job
turns out I just needed "static" on my Item field in my List class. that was extremely hard to find
I'm getting the following error on webpack build and I don't understand why:
SyntaxError: this is a reserved word (11:5)
It occurs inside the Applicatons class at the code which says this.props.apps.map. Its trying to iterate through the passed apps property and create a JSX representation of Application components. I've included the Applications class as the first piece of code and the subsequent code shows how I instantiate the Applications component in a different class. I'm trying to access the props field inside the Applications class which extends the React Component
Here is the Applications class which I am clearly not using React props correctly:
import React from 'react';
import ReactDOM from 'react-dom';
import Application from './Application/Application';
import ErrorBoundary from '../ErrorBoundary/ErrorBoundary';
class Applications extends React.Component {
render(){
let applicationsList=null;
applicationsList = (
{this.props.apps.map((app,index)=>{
return <Application
name={app.name}
desc={app.desc}
changed={(event)=>this.props.changed(event,app.id)}
click={()=>this.props.clicked(index)}
key={app.id}
/>
})}
);
return (
{applicationsList}
)
}
}
And here is the code inside a different react component that instantiates the Applications component.
render(){
let applications=null;
applications = (
<div>
<Applications
apps={this.state.apps}
clicked={this.deleteApplicationHandler}
changed={this.nameChangedHandler}/>
</div>
);
return (<div>{applications}</div>);
}
I'm extremely new to react so i apologize if i missed anything if i did please let me know and ill update the question.
You're trying to use JSX templating syntax outside JSX. Curly brackets are interpreted as defining an object literal. Remove the extra brackets.
render(){
let applicationsList=null;
applicationsList = this.props.apps.map((app,index)=>{
return <Application
name={app.name}
desc={app.desc}
changed={(event)=>this.props.changed(event,app.id)}
click={()=>this.props.clicked(index)}
key={app.id}
/>
});
return applicationsList;
}
I am using a component:- https://github.com/christianalfoni/formsy-react, for creating forms. I am trying to create one of my own components of the input. So as mentioned I need to use it for my's mixin. But unfortunately, there is no support for it in es6 style. So any work around anyone knows of.
here is my component code:-
import Formsy from 'formsy-react';
class DropDownAutoComplete extends React.Component {
constructor(props, context) {
super(props, context);
this.mixins = [Formsy.Mixin];
}
changeValue(event) {
this.mixins[0].setValue(event.currentTarget.value);
}
handleValue1Change(value) {
this.setState({value: value});
}
render() {
const className = this.mixins[0].showRequired() ? 'required' : this.mixins[0].showError() ? 'error' : null;
// An error message is returned ONLY if the component is invalid
// or the server has returned an error message
const errorMessage = this.mixins[0].getErrorMessage();
return <DropdownList
data={this.props.dropDownConfigs.value}
onChange={this.changeValue.bind(this)}
textField={this.props.dropDownConfigs.name}
caseSensitive={false}
filter='contains'>
</DropdownList>
}
}
It's throwing an error where the show required function is called. Apparently, its implementation uses some state variables like required.
By design, mixins do not work with ES6 classes - trying to hack something together is just going to cause you headaches!
One solution is to use what's called a higher-order component - a function that takes in a component, and returns a new component that wraps around it. These wrapper components can have lifecycle hooks of their own, and can pass props down to the wrapped components, effectively providing you with the same functionality mixins would give you, but arguably in a cleaner way!
formsy-react allows you to take this approach, providing its own HOC:
import {HOC} from 'formsy-react';
class MyInput extends React.Component {
render() {
return (
<div>
<input value={this.props.getValue()} onChange={(e) => this.props.setValue(e.target.value)}/>
</div>
);
}
};
export default HOC(MyInput);
You can use react-mixin-decorator.
Quoting from README:
If you're creating React components using ES6 classes and you'd like
to use existing mixins to add some nice functionality to your
component, you probably don't want to take the time to convert the
mixins to something that your ES6 React component class could use.
I have a unknown list of react components to render.
// this is a react component
var DefaultModule = require('./DefaultModule.js');
<DefaultModule/> <--- this will output something because the name is
exactly the class name inside DefaultModule.js
but if I do
// this is a react component
var sssss = require('./DefaultModule.js');
<sssss/> <--- this will not work
so is there a way I can take a list of component names and render them accordingly? Thanks.
p.s: the react component looks like this
import React, {PropTypes, Component} from 'react';
class TestComponent extends Component {
render() {
return (
<div>
1123123123123123 hahaha small test
</div>
);
}
}
export default TestComponent;
I just figured out the answer from a discussion thread...
Yes I can do that but the react component must start in capital letter. so Sssss will work sssss will now.
https://github.com/facebook/react/issues/3365
The key is to use a capitalized variable name (Component) otherwise React will treat it as a built-in DOM element.