I'm learning react and am getting a particular error.
If I try to get my Login and Register classes into the render function of my index file to output it, I am getting the error:
Target container is not a DOM element.
It works fine if my render just has login OR register, but when I combine them both into the one render function it gives the error, I'm unsure how to fix this.
I've tried removing one or the other to double check that it compiles successfully and it does, but when I add the second class it fails.
The code for my render function in my Index.js file is;
import React from "react";
import { render } from "react-dom";
import Login from "./Login";
import Register from "./Register";
render(
<Login />,
<Register />,
document.getElementById("root")
);
The ouput code for my Login file is;
render() {
return (
<form>
<pre>{JSON.stringify(this.state)}</pre>
<button onClick={ event => this.login(event) }>Login</button>
<pre {...(this.state.message.isEmpty ? "hidden" : "")}>
{this.state.message}
</pre>
</form>
);
}
}
export default Login;
and the output code for register is almost identical to logins except and line with 'Login' is 'register'
I need help trying to find out what the problem is so I can fix it.
In this way, I can get my html file to display both buttons and not show the error
Target container is not a DOM element
Thank you.
ReactDOM.render takes one React Node, so you have to wrap your two nodes into another:
render(
<>
<Login />
<Register />
</>,
document.getElementById("root")
);
Related
Just wonder are there any approaches to render component in another component in React.
I render a <Scene /> component like this:
import Scene from './Scene';
ReactDOM.render(<Scene/>, document.getElementById('root'));
And at some point I need to render another component <Building /> (for example on onClick) so that it should be inside <Scene />
At the current I'm trying to do so like this:
import Building from './Building';
ReactDOM.render(<Building/>, document.getElementById('fields'));
And this fields container inside this render() method is a child (pretty deep one) of <Scene />
Yes, it renders, it's located inside #fields in HTML, but if I go to React developer tools I see this:
<Scene></Scene>
<Building></Building>
React just rendering <Building> outside of <Scene> and I need quite the opposite.
Unfortunately, conditional rendering isn't the case.
You should only use one ReactDOM.render(), not multiple. It's common to create 1 component (often named <App />) and in that component you create logic. Basically, you create the whole app in Javascript/ReactJS, and you use that line to "load" it into your html.
export class App extends React.Component{
render(){
// It now returns only one component, but this is where you would put your react router
return(
<Scene />
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
export class Scene extends React.Component{
render(){
return(
<>
<div> Your normal scene here and if you want <Building /></div>
{ orSomeVariableWhichHasToBeTrue && <Building />}
</>
);
}
}
Also, I suggest trying to follow their Basics tutorial, I think you're missing the way React's intended use. Reading the Doc's again might help for some insights.
I'm trying to create a component that both shows the result of some HTML that includes other components and shows the code itself. Basically, a container that demos the markup and shows what markup was used with child components intact. The problem I'm having is that I can only seem to get the fully rendered HTML to display as code when I want he literal input that hasn't been resolved and still includes any component tags that have been used.
<ParentComponent>
<div></div>
<ChildComponent></ChildComponent>
<div></div>
</ParentComponent>
I'd like the ParentComponent to both fully render all of its children, but also treat all HTML within it as a string, essentially, ideally without maintaining two copies of the children. The rendered version is no problem, that happens naturally, but the string form I can't seem to grab from anywhere, it gets the rendered version where ChildComponent is replaced by what it renders as.
I guess this should work for your use case.
import React from "react";
import ReactDOM from "react-dom";
import jsxToString from 'jsx-to-string';
const ParentComponent = props => (
<div>
{`I'm a ParentComponent`}
{props.children}
</div>
);
const ChildComponent = () => <div>{`I'm a ChildComponent`}</div>;
const getParent = () => <ParentComponent>
<div />
<ChildComponent />
<div />
</ParentComponent>;
function App() {
return (
<div className="App">
{getParent()}
{jsxToString(getParent())}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Give it a try.
I am learning react by myself. In my rendering loop I tried to add the element inside so that I can make the hyperlink for each data. But I got this issue:React.Children.only expected to receive a single React element child. Could someone know why it happened? Here is part of my code.Hope it make easier to understand my question. I skipped some parts of my coding as it seems the issue happened in the render part.
app.js
render() {
return (
<Router className="App">
<div>
<nav className="navbar navbar-default">
<div className="container-fluid">
<Link to="/coding-fun">Coding Fun</Link>
</div>
</nav>
<Switch>
// import condingFun.js file as Coding
<Route exact path="/coding-fun" component={Coding} />
<Route path="/coding-fun/:title" component={singleArticle} />
</Switch>
</div>
</Router>
);
}
}
codingFun.js
ps: posts is json data which I didn't add here as too many data.
class Coding extends Component {
render() {
return (
<div className="nav-text">
<h1>Coding fun page</h1>
// posts is data from api, and it renders listPage.js as
ListPage
<ListPage items={posts} />
</div>
);
}
}
export default Coding;
listPage.js
import React, { Component } from "react";
import { BrowserRouter as Link } from "react-router-dom";
class Listing extends Component {
constructor(props) {
super(props);
this.state = { data: this.props.items };
}
render() {
return (
<table>
<tbody>
// loop "post" data from parent component (items) codingFun.js
{this.state.data.map(post => (
<tr key={post.id}>
<td>
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
</td>
<td>{post.content}</td>
</tr>
))}
</tbody>
</table>
);
}
}
If I just add
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
this line, it got "React.Children.only expected to receive a single React element child." issue. If I only add {post.title} in the tag, there is no any issue. So I tried to make the title as link in each row. But I don't know how to make it.
Thanks a lot
The property to does not exist in BrowserRouter. You are also confusing yourself a little bit there by aliasing BrowserRouter with Link because there exists an actual component in react-router called Link. And this is how you use it:
import { Link } from 'react-router-dom'
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
I'm guessing it's because you are doing the import wrong. The import statement should be import { Link } from 'react-router-dom'
You are confusing between Router, Link and Route. So basically,
Router is used to wrap your entire app, to make it fullstack-alike, which means the URL in address bar can be changed and the specific view is rendered respectively
Link is used the same way as <a> tag, which means that it will take you to that URL when clicked
Route, on the other hand, is used to decide what should be rendered under a specific link. This is what you should use to pass children component
In your case, you should change the import statement to:
import { Link } from 'react-router-dom'
Hope this help solve your problem :)
I'm currently switching my web app to react. The old one is located here.
What I'm trying to do is: when an user enter a player's username into the text field and submit, the app would redirect to the corresponding route (/:username), and the text field is cleared.
In the react version, this is what I'm doing currently:
https://github.com/AVAVT/g0tstats-react/blob/master/src/components/SideBar/SearchBox.js
submit(event){
...
this.setState({
redirect : true
});
...
}
And
render(){
...
{
this.state.redirect && (
<Redirect to={`/${this.state.username}`} push />
)
}
}
Which kinda work. But there are 2 things I don't like about it:
I'm rendering an element in order to redirect. It feels stupid and roundabout. It stinks of potential bug in the future.
I'm stuck with the text field not cleared. Because I if I set state.username to null the <Redirect /> component will not redirect correctly. In fact I don't have any precise control over when the redirection occur (unless I do it in another roundabout way).
I have searched for alternative, but couldn't find one. withRouter doesn't work because <SearchBox /> is not a <Route /> and doesn't receive the history props.
So how can I say "redirect me to that place NOW" in react-router v4?
Here is an example that shows when using the withRouter HOC, the routing props get injected to components even if they are not routed to.
Here is my App.js
class App extends Component {
render() {
return (
<div className="App">
<BrowserRouter>
<div>
<Route path='/test' component={Sample} />
<Sibling />
</div>
</BrowserRouter >
</div>
);
}
}
export default App;
Here is my Sample.js. This is like an example container that is rendering a child.
export default class Sample extends React.Component {
render() {
return (
<div>
<span>{this.props.location.pathname}</span>
<br />
<Nested />
</div>
)
}
}
This component can display information about the current route even without the withRouter HOC since it is being routed to.
Here is my Nested.js.
class Nested extends React.Component {
render() {
return (
<div>
<span>I am nested {this.props.location.pathname}</span>
</div>
)
}
}
export default withRouter(Nested);
My nested component needs the withRouter HOC in order to display the current route.
Finally here is my Sibling.js. (This is like your example where <SearchBox /> is a sibling.)
class Sibling extends React.Component {
render() {
return (
<span>{this.props.location.pathname}</span>
)
}
}
export default withRouter(Sibling);
Here all that is needed is to make sure that the sibling is nested within the router as you can see in my App.js, and then using the withRouter HOC it can display the current pathname.
To clarify: If a component can access the current pathname then it can also change the routes programmatically by doing this. this.props.history.push(some path).
I hope this helps.
In one React file, I have the following:
ReactDOM.render(
<BlogButton />,
document.getElementById('nav-blog--react')
);
ReactDOM.render(
<NavButton />,
document.getElementById('nav-home--react')
);
ReactDOM.render(
<PoweredByButton />,
document.getElementById('nav-powered--react')
);
Only the first render works: the "BlogButton" shows up. The other two, "NavButton" and "PoweredbyButton" don't show. I'm not getting an error in the console either. Is that because you can't have multiple renders in a file? How would I combine all of these then into one render call?
Although I can't explain you WHY your example doesn't work - from what I know and have read in the react documentation the "go-to" method is creating 1 main/wrapper component which contains everything else.
You can see the wrapper component as your new DOM to which you append new elements.
I suggest you to create one wrapping component which gets rendered directly into the DOM. While the other elements are rendered within the wrapper component.
WrapperComponent
...
render(
<div>
<FirstComponent />
<SecondComponent />
</div>
);
ReactDOM.render(
<WrapperComponent />,
document.getElementById('nav-powered--react')
);