Pass data from react component - javascript

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;

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

Context empty after async initialisation

I am trying to fetch data from a backend API and initialise my FieldsContext. I am unable to do it, it returns an empty fields array in the Subfields component. I have spent hours on fixing it. But I eventually give up. Please take a look into this. Thanks in advance.
Here is my code
App.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css'
import './App.css';
import Index from './components/pages/index/'
import FieldsProvider from './providers/fieldProvider'
import AuthProvider from './providers/authProvider'
import {BrowserRouter as Router,Switch,Route} from 'react-router-dom';
import SubFields from './components/pages/subfields';
function App() {
return (
<Router>
<AuthProvider>
<FieldsProvider>
<Switch>
<Route exact path="/" component={Index} />
<Route exact path="/:fieldid/subfields" component={SubFields} />
</Switch>
</FieldsProvider>
</AuthProvider>
</Router>
);
}
export default App;
FieldsContext.js
import React from 'react'
const FieldsContext = React.createContext();
export default FieldsContext
FieldsProvider.js
import React, { Component } from 'react'
import FieldsContext from '../libs/fieldContext'
export default class FieldsProvider extends Component {
state = {fields:[]}
getFields()
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
Subfields.js
import React, { Component } from 'react'
import FieldsContext from '../../../libs/fieldContext'
import FieldsList from '../../Fields/fieldlist'
export default class SubFields extends Component {
componentDidMount(){
// const fieldId = this.props.match.params.fieldid;
console.log(this.context);
}
render() {
return (
<div>
</div>
)
}
}
SubFields.contextType = FieldsContext
try using an ES6 Arrow function, which binds the function to the object instance, so that this refers to the object instance of the class when it is called.
When its called asynchronously, this will refer the the class object instance you want to update.
import React, { Component } from 'react'
import FieldsContext from '../libs/fieldContext'
export default class FieldsProvider extends Component {
state = {fields:[]}
// ES6 Arrow function
getFields = () =>
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
Alternatively, Try binding of your function in the class constructor.
export default class FieldsProvider extends Component {
state = {fields:[]}
constructor(props) {
//bind the class function to this instance
this.getFields = this.getFields.bind(this);
}
//Class function
getFields()
{
fetch('/api/fields')
.then(res => res.json())
.then(fields => this.setState({fields}));
}
async componentDidMount() {
await this.getFields();
}
render() {
return (
<FieldsContext.Provider value={this.state} >
{this.props.children}
</FieldsContext.Provider>
)
}
}
As a side note: Prefer to use functional components for consuming of ContextAPI.
import React, { Component } from 'react'
import FieldsContext from '../../../libs/fieldContext'
import FieldsList from '../../Fields/fieldlist'
export default function SubFields (props) {
const {
match
} = props;
//much better way to consume mulitple Contexts
const { fields } = React.useContext(FieldsContext);
//useEffect with fields dependency
React.useEffect(() => {
console.log(fields);
},[fields]);
return (
<div>
</div>
)
}

React: Why won't this React Component render?

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.)

How to test a react component with props?

I need to test a react components with props mounts ok and renders its content such as paras and divs correctly. My code can be found below or in this sandbox
I tried testing it with a default prop but that didn't work.
import React from 'react';
import test from 'tape';
import {mount} from 'enzyme';
test('testing', t => {
t.doesNotThrow(() => {
wrapper = mount(<App2 txt={ok}/>);
}, 'Should mount');
t.end();
});
And this is my component with props.
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import App from './index'
export default class App2 extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
const {txt}=this.props
return (
<div>
<p>hi {txt}</p>
</div>
);
}
}
And the outer component supplying the prop.
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import App2 from './app2'
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p>
Start editing to see some magic happen :)
</p>
<App2 txt={this.state.name}/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
So you would do something like providing the properties yourself and ensuring that it renders with them:
test('test your component', () => {
const wrapper = mount(<App2 txt={'michaelangelo'} />);
expect(wrapper.find('p').text()).toEqual('hi michaelangelo');
});
You shouldn't worry about testing the and html elements like that, but rather the props that you pass and that they render in the right place i.e., in the p tag

What is the best practice to define the properties in react?

I want to code with the best practices.
What is the best practice to define proptypes in a component class in reactjs? And why?
Inside the class:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class MyComponent extends Component {
static propTypes = {
prop: PropTypes
}
render() {
return (
<div> </div>
)
}
};
or Outside the class:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
render() {
return (
<div> </div>
)
}
};
MyComponent.propTypes = {
prop: PropTypes
}
export default MyComponent;
Second option.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
render() {
return (
<div> </div>
)
}
};
MyComponent.propTypes = {
prop: PropTypes
}
export default MyComponent;
Check Clean Code vs. Dirty Code: React Best Practices for reference.

Categories