I am trying to build a view with partials. For this, I created two classes - SmallPost and PostsList.
SmallPost is a small class that renders JSON, like so:
import React from 'react';
import { render } from 'react-dom';
export default class SmallPost extends React.Component {
constructor(props) {
super(props);
this.post = this.props.data;
}
render() {
/* ... */
}
}
And PostsList utilizes it:
import React from 'react';
import { render } from 'react-dom';
import { SmallPost } from './SmallPost';
class PostsList extends React.Component {
constructor(props) {
super(props);
this.list = '/wp-json/wp/v2/posts';
this.posts = null;
this.state = {
posts: null,
loaded: false
}
}
componentDidMount() {
const request = new XMLHttpRequest();
request.open('GET', encodeURI(this.list));
request.onload = () => {
this.setState({
posts: JSON.parse(request.responseText)
}, this.parsePosts);
};
request.send();
}
parsePosts() {
this.posts = this.state.posts.map(post => {
this.setState({ loaded: true });
return (
<SmallPost data={post} />
)
});
}
render() {
if(!this.state.loaded) {
return (<div>Loading...</div>);
} else {
return (<div className="posts--loaded">{this.posts}</div>);
}
}
}
render(<PostsList />, document.getElementById('posts'));
Nothing fancy, as you see. But it doesn't work - I get
Warning: React.createElement: type should not be null,
undefined, boolean, or number. It should be a string (for DOM
elements) or a ReactClass (for composite components).
from console. When I put the SmallPost code inside PostsList file, it works. What can I do?
You're using the default export so you can't use the named import.
So you can change from
import { SmallPost } from './smallpost';
to
import SmallPost from './smallpost';
And if you're using Babel 6.x you might need to do
import SmallPost from './smallpost';
let SmallPostComponent = SmallPost.default;
Related
I was following a tutorial until I got this error. I know that this is caused by some changes on react-router-dom, but I have no idea of how to change this code to the new version, can you give me any suggestions?
import React, { Component } from "react";
import { withRouter } from "react-router";
const parseJwt = (token) => {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch (e) {
return null;
}
};
class AuthVerify extends Component {
constructor(props) {
super(props);
props.history.listen(() => {
const user = JSON.parse(localStorage.getItem("user"));
if (user) {
const decodedJwt = parseJwt(user.accessToken);
if (decodedJwt.exp * 1000 < Date.now()) {
props.logOut();
}
}
});
}
render() {
return <div></div>;
}
}
export default withRouter(AuthVerify);
Here I am trying to set innerHTML from my Test.js on render inside my componentDidMount. On the process I am getting errors of Unhandled Rejection (TypeError): Cannot set property 'innerHTML' of null .
I have gone through few questions where it defined to use refs() but unfotunately not able to use this in my case.
Any suggestion how can I use refs() here in my example?
demo Test.js
function updateList() {
const json = JSON.parse(localStorage["values"]);
if (json) {
picture = json.picture;
if (picture) {
userPicture = picture.name;
}
}
console.log(userPicture, "userPicture");
document.getElementById('picture').innerHTML = userPicture;
}
async function getAll () {
await updateList();
}
export default {
getAll
};
TestComponent.js
import React from 'react';
import Test from './Test';
class TestComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
Test.getAll();
}
render() {
return (
<div className="test-item" >
<div className="test-picture" id="picture"> </div>
</div>
);
}
};
export default (injectIntl(TestComponent));
I believe this is what you want.
Code sandbox url - https://codesandbox.io/s/fervent-surf-n72h6?file=/src/index.js
App.component
import React from "react";
import { render } from "react-dom";
import Test from "./Test";
class App extends React.Component {
constructor(props) {
super(props);
this.divRef= React.createRef();
}
componentDidMount() {
Test.getAll(this.divRef);
}
render() {
return (
<div className="test-item">
<div className="test-picture" ref={this.divRef} id="picture">
Hello from component
</div>
</div>
);
}
}
const container = document.createElement("div");
document.body.appendChild(container);
render(<App />, container);
Test.js
function updateList(ref) {
ref.current.innerHTML = "Hello from Test.js";
}
async function getAll(ref) {
await updateList(ref);
}
export default {
getAll
};
I don't know why i am getting this error can someone please help i have checked the syntax and cant find anything wrong. It's probably something stupid but i just can't find what it is.
import React, { Component } from 'react';
//import Node from './Node/Node';
import { render } from 'react-dom'
import './Pathfinder.css';
export default class Pathfinder extends Component {
constructor(props){
super(props);
this.state = {
grid: [],
};
}
}
render(); {
return (
<div>
{this.startGrid()}
</div>
);
}```
Issue is semicolon after the render keyword.
And render method is outside the class component due to wrongly placed brackets
render(); {}
Change it to
render() {}
Code should look like :
import React, { Component } from 'react';
//import Node from './Node/Node';
import { render } from 'react-dom'
import './Pathfinder.css';
export default class Pathfinder extends Component {
constructor(props){
super(props);
this.state = {
grid: [],
};
}
render() {
return (
<div>
{this.startGrid()}
</div>
);
}
}
I think that you copy-n-paste the code, but you messed up with the curly braces.
import React, { Component } from 'react';
//import Node from './Node/Node';
import { render } from 'react-dom'
import './Pathfinder.css';
export default class Pathfinder extends Component {
constructor(props){
super(props);
this.state = {
grid: [],
};
}
} <-- should be removed
render() { <-- remove the ; sign
return (
<div>
{this.startGrid()}
</div>
);
}
} <-- close your component with curly braces
Tip for every code: Use the correct indentation.
Tip for some codes: Use a linter with prettier.
I'm having a problem with the function fetch. I'm trying to send just a number for example "1", and I have access to this data in all child components, but after calling fetch, I'm no longer able to access this data.
App.jsx:
import React, { Component } from 'react'
import './App.css';
import fetch from 'isomorphic-fetch'
import Header from './Header'
import Content from './Content'
import Footer from './Footer'
class App extends Component {
constructor(props) {
super(props)
this.state = {
stripdata: null
}
}
componentWillMount() {
fetch(`http://localhost:3000/data/info.json`)
.then(results => results.json())
.then(data => {
this.setState({
stripdata: data
})
// console.log(this.state.stripdata)
})
.catch(err => {
console.log("Didn't connect to API", err)
})
}
render() {
// console.log(this.state.stripdata)
return (
<div className="App">
<Header onQuery={1}/>
{
(this.state.data === null) ? <div className="loading">Loading data...</div> : <Content onResult={this.state.stripdata}/>
}
<Footer />
</div>
);
}
}
export default App;
Content.jsx:
import React, { Component } from 'react'
import Result from './Result'
class Content extends Component {
constructor(props) {
super(props);
this.state = {
stripdata: this.props.onResult
};
}
componentWillMount() {
}
render() {
console.log("im an Content: " + this.state.stripdata)
return (
<div className="Content">
<Result stripdata={ this.state.stripdata }/>
</div>
);
}
}
export default Content;
Result.jsx:
import React, { Component } from 'react'
import PersonCard from './PersonCard'
class Result extends Component {
constructor(props) {
super(props);
this.state = {
stripdata: this.props.stripdata
};
}
componentWillMount() {
}
render() {
console.log("im the Result: " + this.state.stripdata)
return (
<div className="result">
<PersonCard />
</div>
);
}
}
export default Result;
Please help. This is blocking my progress.
Fix the issue here:
<Header onQuery={1}/>
{
(this.state.stripdata === null) ? <div className="loading">Loading data...</div> : <Content onResult={this.state.stripdata}/>
}
You need to check properties in state with name stripdata.
And btw, fetch has to be performed in ComponentDidMount, see https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/
The problem is that, in your Results, you are only using the value from props once: in the constructor, where you set to state.
You should not set value in state from props. Instead, just use the props directly. Change Result to as following, then it will work proper:
import React, { Component } from 'react'
import PersonCard from './PersonCard'
class Result extends Component {
constructor(props) {
super(props);
// removed setting state from props.stripdata
}
render() {
console.log("im the Result: " + this.props.stripdata) // <-- using props!
return (
<div className="result">
<PersonCard />
</div>
);
}
}
export default Result;
In general it is considered bad practice/antipattern to set state from props.
I try to get used to reflux and forked a example repo. My full code is here [ https://github.com/svenhornberg/react-starterkit ]
I want to create a timer component which gets the current time from a timestore, but it is not working. The DevTools does not show any errors. This must be some newbie mistakes, but I do not find them.
Edit1: I added a line in home //edit1
Edit2: I think the mistake may be in componentDidMount in home.jsx
FIXED I need to trigger my time, see my answer.
Store
import Reflux from 'reflux';
import TimeActions from '../actions/timeActions';
var TimeStore = Reflux.createStore({
listenables: timeActions,
init() {
this.time = '';
},
onCurrenttime() {
this.time = '13:47';
}
});
export default TimeStore;
Actions
import Reflux from 'reflux';
var TimeActions = Reflux.createActions([
'currenttime'
]);
export default TimeActions;
Component
import React from 'react';
class Timer extends React.Component {
constructor(){
super();
}
render() {
var time = this.props.time;
return (
<div>
{ time }
</div>
);
}
}
Timer.propTypes = {
time : React.PropTypes.string
}
export default Timer;
I wanted to use the timer component in the home.jsx
import React from 'react';
import ItemList from '../components/itemList.jsx';
import ItemStore from '../stores/itemStore';
import ItemActions from '../actions/itemActions';
import Timer from '../components/timer.jsx';
import TimeStore from '../stores/timeStore';
import TimeActions from '../actions/timeActions';
class Home extends React.Component {
constructor(props){
super(props);
this.state = {
items : [],
loading: false,
time : '' //edit1
};
}
componentDidMount() {
this.unsubscribe = ItemStore.listen(this.onStatusChange.bind(this));
this.unsubscribe = TimeStore.listen(this.onStatusChange.bind(this));
ItemActions.loadItems();
TimeActions.currenttime();
}
componentWillUnmount() {
this.unsubscribe();
}
onStatusChange(state) {
this.setState(state);
}
render() {
return (
<div>
<h1>Home Area</h1>
<ItemList { ...this.state } />
<Timer { ...this.state } />
</div>
);
}
}
export default Home;
I fixed it thanks to: How to Make React.js component listen to a store in Reflux
I have to trigger my time:
var TimeStore = Reflux.createStore({
listenables: TimeActions,
init() {
this.time = '';
},
onCurrenttime() {
this.trigger({
time : '13:47'
});
}
});