Hi I am developing an application with React JS.
I have a problem.
TopBottomCard.js
export default class TopBottomCard extends Component {
constructor(props){
super(props)
}
getEnlem(){
return this.props.enlem
}
render() {
return (
<div>
example</div>
)}
Map.js
import TopBottomCard from './TopBottomCard'
export default class Map extends TopBottomCard {
constructor(){
super(this)
}
render() {
const top = new TopBottomCard()
const url = 'https://www.example.com/map.html?'+top.getEnlem+''
console.log(url);
return (
<div style={{height:'100vh'}}>
</div>
)
}
}
When I go to the localhost: 3000 / map page I get an output like this.
Output:
https://www.example.com/map.html?function () { [native code] }
When I change the "url" variable on the Map.js page as follows, it gives an error.
const url = 'https://www.example.com/map.html?'+top.getEnlem()+''
Error code: TypeError: Cannot read property 'enlem' of undefined
How do I solve this?
When you create 'Map' class, make sure the constructor get the props and pass them to the parent, using super(this) will not do the trick.
Also make sure you actually send props to the class you instantiate so it will not be undefined.
class TopBottomCard extends React.Component {
constructor(props){
super(props)
}
getEnlem(){
return this.props.enlem
}
render() {
return (
<div>example</div>
)
}
}
class Map extends TopBottomCard {
constructor(props) { // get the props in this constructor as well
super(props) // and pass them to the parent constructor
}
render() {
const top = new TopBottomCard({}) // you need to send props so it will not be undefined in the component
const url = 'https://www.example.com/map.html?' + top.getEnlem() + ''
return (
<div style={{height:'100vh'}}>
</div>
)
}
}
Related
so I'm having a little trouble using ref's with React.
All I'm trying to do is print the text content of an element using ref's like this:
export default class SomeClass extends Component {
constructor(props) {
super(props);
this.intro = React.createRef();
console.log(this.intro.textContent);
}
render() {
return (
<div ref={this.intro}>Hi</div>
)
}
}
However, this always prints null or undefined instead of "Hi" which is what I want.
You should use current with ref, like this.ref.current.textContent
Check the stackblitz demo Here
export default class App extends Component {
constructor(props) {
super(props);
this.intro = React.createRef();
}
componentDidMount(){
console.log( this.intro.current.textContent);
}
render() {
return (
<div ref={this.intro}>Hi</div>
)
}
}
Its because you are logging it in constructor. Run the code in componentDidMount lifecyle.
export default class SomeClass extends Component {
constructor(props) {
super(props);
this.intro = React.createRef();
}
componentDidMount(){
console.log(this.intro.textContent);
}
render() {
return (
<div ref={this.intro}>Hi</div>
)
}
}
You are console logging in the constructor before Dom is actually rendered.
Try console logging in an onClick handler instead.
export default class SomeClass extends Component {
constructor(props) {
super(props);
this.intro = React.createRef();
}
print = () => {
console.log(this.intro.textContent);
}
render() {
return (
<div>
<div ref={this.intro}>Hi</div>
<button onClick={this.print}>Print</div>
</div>
)
}
}
So I am building my first react project and stumbled upon following problem:
In my App.js (main application) I got a function and render my components:
class App extends Component {
constructor(props) {
super(props);
this.candidateCounter = 0;
this.setCandidateVote = this.setCandidateVote.bind(this);
}
...
setCounter (name) {
this.candidateCounter++;
console.log(this.candidateCounter);
}
render() {
...
<Candidates setCounter={this.setCounter} />
}
}
The child component Candidates.jsx has another function and thus calls another component:
export class Candidates extends React.Component {
constructor(props) {
super(props);
this.AppProps = props;
}
...
registerVote(name) {
...
this.AppProps.setCounter(name);
}
render() {
...
<MyButton id={this.state.candidates[i].name} register={this.registerVote} />
}
And the last component MyButton.jsx looks like this:
export class MyButton extends React.Component {
constructor(props) {
super();
this.ParentProps = props;
this.state = { active: false }
}
buttonActiveHandler = () => {
this.setState({
active: !this.state.active
});
if (this.state.active === false) {
this.ParentProps.register(this.ParentProps.id);
}
else {
...
}
}
render() {
return (
<Button content='Click here' toggle active={this.state.active} onClick={this.buttonActiveHandler} />
);
}
}
I have successfully debugged that all functions calls are working except when the grandchild MyButton has triggered the registerVote() function in my Candidates module. Logging in this method gets printed but it cannot call this.AppProps.setCounter() from the parent App. I receive the following error:
TypeError: Cannot read property 'setCounter' of undefined
I hope this wasn't too complicated explained, any help is appreciated :)
Simply bind the function in the constructor of the class as #qasimalbaqali stated in his comment.
constructor(props) {
super();
this.registerVote = this.registerVote.bind(this);
}
Let say I have this Parent
const Parent = () => <ChildComponent foo={<Button>clic</Button>} />
why would this code work
class ChildComponent extends React.Component {
render() {
return (
<div>
{this.props.foo}
</div>
)
}
}
but this code would not ?
class ChildComponent extends React.Component {
constructor(props) {
super(props)
const ParentButton = this.props.foo
}
render() {
return (
<div>
<ParentButton />
</div>
)
}
}
I need something like the second example in order to add some event to ParentButton.
I'd like to make this example work with class defined component
Update :
Based on answer I now have a partial solution
class ChildComponent extends React.Component {
constructor(props) {
super(props)
this.ParentButton = this.props.foo
}
render() {
return (
<div>
{this.ParentButton}
</div>
)
}
}
You're not assigning ParentButton to the ChildComponent.
What you currently have is a const floating in the constructor since const, let and var keywords are function/block scoped.
this. ParentButton = this.props.foo and succinctly <this. ParentButton > in your render function will get you what you're after.
After running this code - I got the exception that "title" is not defined. I checked that api returns correct data. And on the debug mode I noticed that render() from Idea component is running earlier than getting the data from API. Can you explain why is it working in this way? And what options I have for resolving this issue?
Thanks
'use strict';
const React = require('react');
const ReactDOM = require('react-dom');
const client = require('./client');
class App extends React.Component {
constructor(props) {
super(props);
this.state = {map: {}};
}
componentDidMount() {
client({method: 'GET', path: '/api/maps/1'}).done(response => {
this.setState({map: response.entity._embedded.map});
});
}
render() {
return (
<Map map={this.state.map}/>
)
}
}
class Map extends React.Component {
render() {
return (
<div id="map_header">
<AddIdeaButton></AddIdeaButton>
<Idea idea={this.props.map.root}></Idea>
</div>
);
}
}
class AddIdeaButton extends React.Component {
render() {
return (
<a id="btn_add">
</a>
);
}
}
class Idea extends React.Component {
render() {
<div id="root">{this.props.idea.title}</div>
}
}
ReactDOM.render(
<App />,
document.getElementById('react')
);
Asynchronous request for data takes some time during which React still renders Map and Idea components. You can simply render Idea conditionally when data is available:
<div id="map_header">
<AddIdeaButton></AddIdeaButton>
{this.props.map.root && (
<Idea idea={this.props.map.root}></Idea>
)}
</div>
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
};