Cannot find react component - angularjs

It throw me Error: Cannot find react component myTable.. i have that react..
var myTable = React.createClass({
render:function () {
return(
<div>
<table className="table scroll2" >
<thead>
<tr>
<td>Start Date</td>
<td>End Date</td>
<td>Hours</td>
<td></td>
</tr>
</thead>
{
this.props.list.map(function (item,i) {
return(
<tr>
<td>{item.startDate}</td>
<td>{item.endDate}</td>
<td>{item.workInHours}</td>
</tr>
);
})
}
</table>
</div>
);
}
});
angular.module('app').value('myTable',myTable);
and i call that with this :
<react-component name="myTable"></react-component>

Declare your component like this (notice the Pascal Casing):
var MyTable = React.createClass({ ... })
Use your component like this instead:
<MyTable />
As Justin has pointed out correctly, React class names must start with an upper-case letter, otherwise it will be interpreted as html tag. Thus, a lot of people follow Pascal Case.
From the official docs:
To render a React Component, just create a local variable that starts with an upper-case letter
JSX in Depth: HTML Tags vs. React Components

#Mario Tacke You're right with the exception that it HAS to be pascal cased if its a React element, otherwise it will be interpreted as a HTML tag element and not a react one.
More about it here https://gist.github.com/sebmarkbage/f1f4ba40816e7d7848ad

Related

In react bootstrap how do I show the contents of an array in an html table

I have an array that I add to, each time a button is pressed. That part appears to work. When I output it to a console, I can see that each one is getting added.
const addToPool = () => {
diePool[poolCount] = (
<die
type={diceType}
number={diceNumber}
adjuster={diceAdjuster}
/>
);
poolCount++;
};
How do I loop through and display that in my html table after my form?
return (
<div className="App">
<header className="App-header">
<Form>
<Button onClick={addToPool} aria-controls="diceRoll" aria-expanded={open} variant="secondary" size="sm">
Add to Pool
</Button>
</ButtonToolbar>
</Form>
<Fade in={open}>
<div id="diceRoll">
The result is: {randNum}
</div>
</Fade>
</header>
<Table responsive>
<caption>Dice Pool</caption>
<thead>
<tr>
<th>Type</th>
<th>Number</th>
<th>Adjuster</th>
</tr>
</thead>
<tbody>
</tbody>
</Table>
</div>
);
}
export default App;
In order for React to update the user interface to reflect changes, it expects you to notify it that a change has been made. You do this my modifying the state of your component. In your addToPool method, you are modifying a local variable called diePool. That's just a member variable of the control object, not the state, and React won't know you've made a change.
Instead, modify the state with something like this:
const addToPool(diceType, diceNumber, diceAdjuster) {
this.setState(prevstate => {
return {
diePool: prevstate.diePool.push(
{ type: diceType, number: diceNumber, adjuster: diceAdjuster }
)
}
});
}
For this to work, your component will have to have an initial state to work with. You create this in the constructor:
constructor(props) {
this.state = { diePool: [] };
}
Now, whenever your code calls addToPool, the state will be updated and through setState, React will know about it and call the render method as needed.
In your render method, you will need to consult the state to place the dice rolls in your table. You can do so by using map over your array of dice rolls:
<Table responsive>
// ...snip...
<tbody>
{this.state.diePool.map((roll, index) => {
<tr key={index}>
<td>{roll.type}</td>
<td>{roll.number}</td>
<td>{roll.adjuster}</td>
</tr>
})}
</tbody>
</Table>
(Please note the use of index here to make sure that each table row has a unique index - this is a requirement for React to be able to update table rows individually when it can.)
What's important here is that the component state is a crucial concept in React. If you modify something and you expect React to react (ha!) to it, you'll have to modify the state through setState (not by modifying this.state directly). That's the only way React will know about it. React will then work its magic and call the render methods of your component and its children, as necessary.
inside your body tag, you can iterate through an array using the map method (https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/map)
<tbody>
{dice.map((item,index) => {
return(
<tr key={index}>
<td>{item.key1}</td>
etc...
</tr>
)})}
</tbody>
I figured it out and posting it here in case others have trouble:
declared a counter:
const [poolCount, setPoolCount] = useState(0);
Created my addToPool:
const addToPool = () => {
setDiePool([
...diePool,
{
dp1 : poolCount,
dp2 : diceType,
dp3 : diceNumber,
dp4 : diceAdjuster
}
]);
setPoolCount(poolCount+1);
};
Call my addToPool when I click the button:
<Button onClick={addToPool} aria-controls="diceRoll" aria-expanded={open} variant="secondary" size="sm">
Add to Pool
</Button>
Then create my table and loop:
<Table responsive>
<caption>Dice Pool</caption>
<thead>
<tr>
<th>#</th>
<th>Type</th>
<th>Number</th>
<th>Adjuster</th>
</tr>
</thead>
<tbody>
{diePool.map(die => (<tr key={die.dp1}><td>{die.dp1}</td><td>{die.dp2}</td><td>{die.dp3}</td><td>{die.dp4}</td></tr>))}
</tbody>
</Table>

React: validateDOMNesting: #text cannot appear as a child of <tr>

Can you explain me why react show warning Warning: validateDOMNesting(...): #text cannot appear as a child of <tr>. See Router > RouterContext > CarWashPage > AllCarWashTable > tr > #text.? I don't see any text inside tag tr
Code that renders table
export default class AllCarWashTable extends React.Component{
constructor(props) {
super(props);
this.generateHeaders = this.generateHeaders.bind(this);
this.generateRows = this.generateRows.bind(this);
};
static propTypes = {
cols : React.PropTypes.array.isRequired,
rows : React.PropTypes.array.isRequired
}
generateHeaders() {
let cols = this.props.cols; // [{key, label}]
return cols.map(function(colData) {
return <th key={colData.key}> {colData.label} </th>;
});
}
generateRows() {
let cols = this.props.cols, // [{key, label}]
data = this.props.rows;
if (this.props.rows.length > 0) {
return data.map(function(item) {
var cells = cols.map(function(colData) {
return <td key={colData.key}> {item[colData.key]} </td>;
});
return <tr key={item.id}> {cells} </tr>;
});
}
}
render(){
let headers = this.generateHeaders();
let rows = this.generateRows();
return (
<table className="table table-hove">
<thead>
<tr>
{headers}
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
)
}
}
At the end, my table has the following structure
Where is the problem?
The problem is the spaces in this line:
return <tr key={item.id}> {cells} </tr>;
It might seem silly, but you're actually rendering the cells and some whitespace (i.e. text). It should look like this:
return <tr key={item.id}>{cells}</tr>;
This will also happens when using logical AND short-circuit && to show/hide conditional rows:
{
foo && (<tr><td>{foo}</td></tr>)
}
change it to ternary a ? b : c form where c is null will fix it
{
foo ? (<tr><td>{foo}</td></tr>) : null
}
In my case where was an empty '' output (w\o space inside)
<tbody>
{this.props.orders.map(
order =>this.props.selectedAgent === order.agent ?
<Row item={order} key={ order._id } /> : ''
)
}
</tbody>
The null does the trick:
<tbody>
{this.props.orders.map(
order =>this.props.selectedAgent === order.agent ?
<Row item={order} key={ order._id } /> : null
)
}
</tbody>
The accepted answer wasn't the root cause in my case. I got the same warning when I had a comment after <th> tag. The warning went away when I removed the comment.
const TableHeaders = (props) => (
<tr>
<th>ID</th> {/* TODO: I had a comment like this */}
</tr>
)
EDIT: Removing the space between </th> and {/* will also do the trick.
A <tr> HTML tag indicates a table row. So, any text to be displayed inside a table row must be placed inside <td> HTML tag. This would remove the error.
Example:
return (
<tr>
<td> {/* Using <td> inside <tr> */}
Hello World!
</td>
</tr>
);
Notification warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of <tbody>. Make sure you don't have any extra white space between tags on each line of your source code.
In my case, initialize variable should NOT is null.
let elementCart = ''; {/* in the here,warning will append */}
if(productsCart.length > 0){
elementCart = productsCart.map((item, index) => {
return <CartItem item={item} key={index} index={index} />
});
}
return(
<tbody id="my-cart-body">
{elementCart}
</tbody>
)
Solution: let elementCart = null;
Incase anyone else comes across this error or a similar whitespace error with Material UI in React, my solution after hours of breaking my code was a simple javascript comment inside of my table.
{ /* sortable here */ }
I removed that from between my table elements and the warning disappeared.
Make sure the let variables are valued otherwise initialize a new empty array.
{headers ? headers : []}
or
{rows || []}
For me it works like a charm ...
render(){
let headers = this.generateHeaders();
let rows = this.generateRows();
return (
<table className="table table-hove">
<thead>
<tr>
{headers ? headers : []}
</tr>
</thead>
<tbody>
{rows || []}
</tbody>
</table>
)
}
also || null can solve it.
the important is that the value is not ''
Kevin Law (from other comment) said that you can do this:
{
foo ? (<tr><td>{foo}</td></tr>) : null
}
But you can also fix it like this:
{
Boolean(foo) && <tr><td>{foo}</td></tr>
}
Removing the comment is what helped me too
in my case initialize a variable with null instead of "" works fine
In addition to #Jarno's answer, I also ran into this issue as well. Double check that you don't have any additional } or { at the end of your javascript code:
{this.props.headers.map(header => <th key={header}>{header}</th>)}}
↑
I received this warning when I had a parenthesis instead of a curly bracket
<table>
<tbody>
<tr>
(showMsg && <td>Hi</td>} // leading '(' should be a '{'
</td>
</tbody>
</table>
I received this warning when I put text inside <tr> element with no <td> elements. I wrapped my text with <td> elements and the warning disappeared.
When I did this, having a whitespace in my text or having used {} didn't matter.
In my case I indeed had a <tr> inside a <tr> (intended to use <td>) :)
It's very easy to find. Just open your inspect and look for tag. It should appear at the beginning or at the end of the tag a quoted string like this:
You shouldn't pass an unexpected element in the table body tag. You should use tr and td
In your rows would return the element with tr and td
{rows}
Something like
return(
<tr>
<td>
Hello
</td>
</tr>
)
For my situation, I was getting this error because I forgot to update a SQL query to include an updated column name. The original query was trying to access a column that didn't exist.
This query was being used with Nextjs, React, Material UI and sent to a PostgreSQL server in order to load up a MUI front-end table with database information from the table.
Updating the query fixed the issue.

Which one is your preferred way of declaring Stateless functional components in React.js and Why ?

Function Declaration
function MyComponent(props, context) {}
Function Expression
const MyComponent = function(props, context){}
Arrow function
const MyComponent = (props, context) => {}
Function Declaration if you want hoisting and prefer readability over performance.
Function Expression if you want to name your function so you can identify it easier from debugging stack traces (e.g from Chrome dev tools).
Arrow Function if you want if you don't care about having an anonymous function in your stack trace and want to avoid binding this.
My stateless components look like this, which seems very clean to me and pretty much looks just like HTML. Also, es6 arrow functions assume the return expression if you dont use brackets, so you can leave those out:
const Table = props =>
<table className="table table-striped table-hover">
<thead>
<tr >
<th>Name</th>
<th>Contact</th>
<th>Child Summary</th>
</tr>
</thead>
<tbody>
{props.items.map(item => [
<TableRow itemId={item.id} />,
item.isSelected && <TableRowDetails itemId={item.id} />
])}
</tbody>
</table>

reactjs table render - how to handle empty rows rendering for tbody

I am very new to ReactJS and playing around to learn its tricks of the trade. I am trying to create a simple table with thead and tbody.
my code looks as below:
/**
* creates a HTML table to show requirements
**/
var ReqTable = React.createClass({
render: function() {
var rows = [];
rows = this.props.data.map(function(row) {
return ( <ReqRow row={row} />);
});
return(
<table className="reqTable table table-bordered table-striped">
<thead>
<tr>
<th>REQ #</th>
<th>Short Desc</th>
<th>Long Description</th>
</tr>
</thead>
<tbody> {rows} </tbody>
</table>
);
}
});
I am using ajax call to get the rows and render this table. This works fine overall, but gives a warning in the browser console, indicating that you cannot add a span inside a tbody.
I am sure I am not adding a span. But what I believe is that when there are no rows (when render is first time called), it seems reactJS is trying to render a span inside the tbody.
So, should I put an if check here to avoid rendering a span? Finally what is the correct way to render a empty set of rows in tbody?
Your issue is that you have space characters as children of your tbody element, before and after your rows array:
<tbody> {rows} </tbody>
Compiles to:
React.createElement("tbody", null, " ", rows, " ");
Because of DOM limitations, when a DOM component has more than one child, React wraps all its text children within <span> elements. So the above JSX is equivalent to:
<tbody><span> </span>{rows}<span> </span></tbody>
To fix this, just remove the extraneous characters:
<tbody>{rows}</tbody>

How to correctly wrap few TD tags for JSXTransformer?

I have an array with items and I want to make something like this:
<tr>
(until have items in array
<td></td><td></td>)
</tr>
But if I do that, I get an JSXTransformer error :
Adjacent XJS elements must be wrapped in an enclosing tag
Working version:
{rows.map(function (rowElement){
return (<tr key={trKey++}>
<td className='info' key={td1stKey++}>{rowElement.row[0].value}</td><td key={td2ndKey++}>{rowElement.row[0].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[1].value}</td><td key={td2ndKey++}>{rowElement.row[1].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[2].value}</td><td key={td2ndKey++}>{rowElement.row[2].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[3].value}</td><td key={td2ndKey++}>{rowElement.row[3].count}</td>
<td className='info' key={td1stKey++}>{rowElement.row[4].value}</td><td key={td2ndKey++}>{rowElement.row[4].count}</td>
.......
</tr>);
})}
I tried this one. But with <div> enclosing tag it doesn't work fine.
Answer here:
Uncaught Error: Invariant Violation: findComponentRoot(..., ...$110): Unable to find element. This probably means the DOM was unexpectedly mutated
<tbody>
{rows.map(function (rowElement){
return (<tr key={trKey++}>
{rowElement.row.map(function(ball){
console.log('trKey:'+trKey+' td1stKey'+td1stKey+' ball.value:'+ball.value+' td2ndKey:'+td2ndKey+' ball.count:'+ball.count);
return(<div key={divKey++}>
<td className='info' key={td1stKey++}>{ball.value}</td><td key={td2ndKey++}>{ball.count}</td>
</div>);
})}
</tr>);
})}
</tbody>
Please, advise me how to properly wrap few TD tags!
I tried use a guide Dynamic Children, but JSXTransformer doesn't allow me do that.
The following error usually occurs when you are returning multiple elements without a wrapping element
Adjacent XJS elements must be wrapped in an enclosing tag
Like
return (
<li></li>
<li></li>
);
This doesn't work because you are effectively returning two results, you need to only ever be returning one DOM node (with or without children) like
return (
<ul>
<li></li>
<li></li>
</ul>
);
// or
return (<ul>
{items.map(function (item) {
return [<li></li>, <li></li>];
})}
</ul>);
For me to properly answer your question could you please provide a JSFiddle? I tried to guess what you're trying to do and heres a JSFiddle of it working.
When using the div as a wrapper its actually never rendered to the DOM (not sure why).
<tr data-reactid=".0.0.$1">
<td class="info" data-reactid=".0.0.$1.$0.0">1</td>
<td data-reactid=".0.0.$1.$0.1">2</td>
<td class="info" data-reactid=".0.0.$1.$1.0">1</td>
<td data-reactid=".0.0.$1.$1.1">2</td>
<td class="info" data-reactid=".0.0.$1.$2.0">1</td>
<td data-reactid=".0.0.$1.$2.1">2</td>
<td class="info" data-reactid=".0.0.$1.$3.0">1</td>
<td data-reactid=".0.0.$1.$3.1">2</td>
</tr>
EDIT: React 16+
Since React 16 you can now use fragments.
You would do it like this now
return <>
<li></li>
<li></li>
<>;
Or you can use <React.Fragment>, <> is shorthand for a HTML fragment, which basically is just a temporary parent element that acts as a container, once its appended to the document it no longer exists.
https://reactjs.org/docs/fragments.html
https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
So you have pairs of <td> elements which you want to return from a .map. The easiest way to do this is to just wrap them in an array.
<tr>
{data.map(function(x, i){
return [
<td>{x[0]}</td>,
<td>{x[1]}</td>
];
})}
</tr>
Don't forget the comma after the first </td>.
With the release of React 16, there is a new component called Fragment.
If are would like to return a collection of elements/components without having to wrap them in an enclosing element, you can use a Fragment like so:
import { Component, Fragment } from 'react';
class Foo extends Component {
render() {
return (
<Fragment>
<div>Hello</div
<div>Stack</div>
<div>Overflow</div>
</Fragment>
);
}
}
Here is how you will do it
<tbody>
{this.props.rows.map((row, i) =>
<tr key={i}>
{row.map((col, j) =>
<td key={j}>{col}</td>
)}
</tr>
)}
</tbody>

Resources