React: Why won't this React Component render? - javascript

I'm in the process of writing a desktop application in React using Electron and Meteor.js
I have the following React Component class:
import React from "react"
export class MemoryMap extends React.Component{
constructor(props){
super(props);
this.state = {
memory : [],
mem_max : 0xFFFF,
}
this.readByte = function(byte){
return this.state.memory[byte];
};
this.writeByte = function(mem_addr, byte){
if(mem_addr >= 0 && mem_addr < this.state.mem_max) {
this.state.memory[mem_addr] = byte;
}
};
for(let i = 0; i < 10000; i++){
this.state.memory[i] = 0x0000;
}
}
render(){
return(
<div>
<h1>{this.state.memory[0x0000]}</h1>
</div>
);
}
}
export const MemMap = new MemoryMap();
I attempt to render this class in Main.jsx as such:
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import {MemMap} from "./CPU_Elements/MemoryMap";
Meteor.startup(() => {
render(<MemMap/>, document.getElementById("react-target"));
Desktop.send("desktop", "init");
});
When called this way, the program crashes on this line. The Desktop.send function is never called.
If I re-write MemoryMap as such, where the render function becomes a class method:
import React from "react"
export class MemoryMap extends React.Component{
constructor(props){
super(props);
this.state = {
memory : [],
mem_max : 0xFFFF,
}
this.readByte = function(byte){
return this.state.memory[byte];
};
this.writeByte = function(mem_addr, byte){
if(mem_addr >= 0 && mem_addr < this.state.mem_max) {
this.state.memory[mem_addr] = byte;
}
};
for(let i = 0; i < 10000; i++){
this.state.memory[i] = 0x0000;
}
this.render = function(){
return(
<div>
<h1>{this.state.memory[0x0000]}</h1>
</div>
);
}
}
}
export const MemMap = new MemoryMap();
And the main.jsx file is re-written to call that method:
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import {MemMap} from "./CPU_Elements/MemoryMap";
Meteor.startup(() => {
render(MemMap.render(), document.getElementById("react-target"));
Desktop.send("desktop", "init");
});
The element renders just fine.
Why is this? Why can't I use the HTML tag formatting, as shown in React's tutorials?

change this:
export const MemMap = new MemoryMap();
to:
export const MemMap = MemoryMap;
Since you should export the component defination, not creating an instance of it and exporting it. (that's why obj.render() works but <obj/> doesn't.)

Related

REACT Component to REACT Function

I have to implement hooks in my Component, but as far as I know it is not possible using the hooks in a REACT.Component.. I am new at REACT and I donĀ“t really have an Idea how I can convert my Component to a function correctly. Can someone show me how to convert the content from my Component to this function?
My Component:
import React from "react";
import { sessionId } from "../common/urlHandler";
import { Settings } from "../settings";
import { Constants } from "../common/constants.js";
import OrderHistoryService from "../services/orderHistory/orderHistoryService";
import OrderHistoryTable from "../orderHistory/orderHistoryTable";
import OrderHistoryPagination from "../orderHistory/orderHistoryPagination";
import OrderHistorySearchField from "../orderHistory/orderHistorySearchField";
export default class OrderHistoryPage extends React.Component {
constructor(props) {
super(props);
const orderHistoryService = new OrderHistoryService(
Settings.baseUrl,
this.props.lang
);
this.state = {
orderHistoryService: orderHistoryService,
sessionId: sessionId(),
orderHistoryData: Constants.DummyOrderHistory,
};
}
componentDidMount() {
//fixMe: fetch-Data and set orderHistoryData
}
render() {
if (this.state.orderHistoryData !== null) {
return (
<section className="section">
<div><OrderHistorySearchField /></div>
<div><OrderHistoryPagination /></div>
<div><OrderHistoryTable orderHistoryData={this.state.orderHistoryData} /></div>
</section>
);
}
}
}
The function into I want to convert my Component:
export default function OrderHistoryPage () {
//fill with data from my Component
}
It should be like this basically you should use useState for states and useEffect for componentDidMount. Also you should remove things that does not exist in functional components like render and this.
import React, {useState, useEffect} from "react";
import { sessionId } from "../common/urlHandler";
import { Settings } from "../settings";
import { Constants } from "../common/constants.js";
import OrderHistoryService from "../services/orderHistory/orderHistoryService";
import OrderHistoryTable from "../orderHistory/orderHistoryTable";
import OrderHistoryPagination from "../orderHistory/orderHistoryPagination";
import OrderHistorySearchField from "../orderHistory/orderHistorySearchField";
export default function OrderHistoryPage (props) {
const orderHistoryService = new OrderHistoryService(
Settings.baseUrl,
props.lang
);
const [orderHistoryService, setorderHistoryService] = useState(orderHistoryService);
const [sessionId, setSessionId] = useState(sessionId());
const [orderHistoryData, setOrderHistoryData] = useState(Constants.DummyOrderHistory);
useEffect(()=> {
//fixMe: fetch-Data and set orderHistoryData
}, []);
return (
{ (orderHistoryData !== null) &&
(<section className="section">
<div><OrderHistorySearchField /></div>
<div><OrderHistoryPagination /></div>
<div><OrderHistoryTable orderHistoryData={this.state.orderHistoryData} /></div>
</section>) }
);
}

Mobx-react no render but state changed

I decided to try Mobx and faced the problem of the component's lack of response to a changing field in the repository. I looked at similar topics, but I still don't understand what the problem is. If you print the property value to the console after the change, you see the actual result.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from "mobx-react";
import AppStore from "./AppStore";
import App from './App';
ReactDOM.render(
<React.StrictMode>
<Provider AppStore={AppStore}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
App.js
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
#inject('AppStore')
#observer class App extends Component {
render() {
const { AppStore } = this.props;
console.log(AppStore);
return(
<div className="App">
{ this.props.AppStore.counter }
<hr/>
<button onClick={this.props.AppStore.increment}>+</button>
<button onClick={this.props.AppStore.decrement}>-</button>
</div>
)
}
}
export default App;
AppStore.js
import { observable, action } from "mobx";
class AppStore {
#observable counter = 0;
#action increment = () => {
this.counter = this.counter + 1;
console.log(this.counter);
}
#action decrement = () => {
this.counter = this.counter - 1;
console.log(this.counter);
}
}
const store = new AppStore();
export default store;
Since mobx#6.0.0 decorators are not enough. You have to make your class observable manually with makeObservable as well.
class AppStore {
#observable counter = 0;
constructor() {
makeObservable(this);
}
#action increment = () => {
this.counter = this.counter + 1;
}
#action decrement = () => {
this.counter = this.counter - 1;
}
}

Pass data from react component

I have a GetData.js component that gets API data and sets it to an array. I want to access that array data in multiple other components and manipulate it in multiple different ways.
For example, I want to be able to do something like this:
import APIdata from './GetData';
var data = APIdata.object;
var result = [];
if (data) {
for (var i = 0; i < data.length; i++) {
if (data.form_values["6f71"] === "KeyWord") {
result.push(data)
}
}
}
You're looking at a fairly straightforward use of container components, props, and state.
Here's a contrived example:
import React, {Component} from 'react';
import OtherComponent1 from './OtherComponent1';
import OtherComponent2 from './OtherComponent2';
class GetDataComponent extends Component {
constructor() {
super(props);
this.state = {
data: []
}
}
fetchMyData() {
const resultingArray = ...
this.setState({data: resultingArray});
}
componentDidMount() {
this.fetchMyData();
}
render() {
return (
<div>
<OtherComponent1 someArrayProp={this.state.data}/>
<OtherComponent2 differentArrayProp={this.state.data}/>
</div>
);
}
}
export default App;
import React, {Component} from 'react';
import PropTypes from 'prop-types';
class OtherComponent1 extends Component {
render() {
return (
<div>
The someArrayProp: {this.props.someArrayProp}
</div>
);
}
}
OtherComponent1.propTypes = {
someArrayProp: PropTypes.array;
}
export default App;
import React, {Component} from 'react';
import PropTypes from 'prop-types';
const OtherComponent2 = (props) => (
<div>
The differentArrayProp: {props.differentArrayProp}
</div>
);
OtherComponent2.propTypes = {
differentArrayProp: PropTypes.array;
}
export default App;

React and importing classes

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;

own timer component with react, reflux not working

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'
});
}
});

Categories