While using React Context API ,unable to fetch data - reactjs

This is my App.js , I am using context api but I am unable to fetch
data at {context.country} and {context.job} which is in child
component i.e Neighbour.
This is my App.js , I am using context api but I am unable to fetch
data at {context.country} and {context.job} which is in child
component i.e Neighbour.
App.js
import React, { Component } from 'react';
import Neighbour from './Neighbour';
const MyContext = React.createContext();
class MyProvider extends Component {
state = {
firstName: 'Tom', lastName: 'Holland', age: 24, country: 'America', job: 'Actor',
}
render() {
return (
<MyContext.Provider value={{
state: this.state, growOld: () => this.setState({ age: this.state.age + 1 })
}}>
{this.props.children}
</MyContext.Provider>
);
}
}
class App extends Component {
render() {
return (
<div className="App">
<MyProvider value={{ state: this.state }}>
<div>
<p>I am in App component</p>
<Family />
<br />
<Neighbour />
</div>
</MyProvider>
</div>
);
}
}
export default App;
Neighbour.js
import React, { Component } from 'react';
const MyContext = React.createContext();
class Neighbour extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
<MyContext.Consumer>
{context => (
<React.Fragment>
<p>Country : {context.country}</p>
<p>Job : {context.job}</p>
</React.Fragment>
)}
</MyContext.Consumer>
</div>
);
}
}
export default Neighbour;

Since you are providing the value as object {state: this.state} to context, you need to use it like context.state.country in your consumer.
<MyContext.Consumer>
{context => (
<React.Fragment>
<p>Country : {context.state.country}</p>
<p>Job : {context.state.job}</p>
</React.Fragment>
)}
</MyContext.Consumer>
or you Provide the value in provider like
<MyProvider value={this.state}>
<div>
<p>I am in App component</p>
<Family />
<br />
<Neighbour />
</div>
</MyProvider>
Also in Neighbour component you re creating a context again which doesn't have a Provider and hence the value in Consumer would come undefined, you need to import the same context that you have used the Provider on
In Neighbour.js
Neighbour.js
import React, { Component } from 'react';
inport { MyContext } from 'path/to/context';

Related

Splitting code into files using context api

I'm using context API for the first time.I can understand how to write the code in a single page.But I can't understand how to split it into several files.When I split it as below it gives me an error saying that I have not exported MyProvider.But I have done it.I searched for many video tutorials but I couldn't find a one that matches to my problem
App.js
import {MyProvider} from './Context';
import {myContext} from './Context';
class Name extends Component {
render() {
return (
<div>
<myContext.Consumer>
{(context) => (
<React.Fragment>
<h1>Hello, {context.state.name}</h1>
<h3>{context.state.address}</h3>
</React.Fragment>
)}
</myContext.Consumer>
</div>
);
}
}
class Age extends Component {
render() {
return (
<div>
<myContext.Consumer>
{(context) => (
<React.Fragment>
<h1>You are {context.state.age} years old</h1>
<h3>You were born in - {context.state.dob}</h3>
</React.Fragment>
)}
</myContext.Consumer>
</div>
);
}
}
class App extends Component {
render() {
return (
<MyProvider>
<div className="App">
<Name />
<Age />
</div>
</MyProvider>
);
}
}
export default App;
Context.js
export const myContext = React.createContext();
class MyProvider extends Component {
state = {
name: "Sam",
address: "No.35,Main Street,Galle",
age: 50,
dob: "1970-10-21"
}
render() {
return (
<myContext.Provider value={{
state: this.state
}}>
{this.props.children}
</myContext.Provider>
)
}
}
export default MyProvider;
You have a mistake in import. When you export as default, you should import it without curly braces.
export default CLASS
import CLASS from
Or you can export your class as export class, then you will import it as you do:
export class A
import { A }
UPD:
Please take a look at
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export

Unable to send state data as props to another component

I am new to react. And I am trying to build an electron app using react js.
I want to send a parent component state value to child component as props.
The parent component is Home, and the child component is Help.
Home.jsx
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
step: 1,
name: "",
address: "",
amount: "",
}
}
handleChange = (e) => {
let nam = e.target.name;
let val = e.target.value;
this.setState({ [nam]: val });
}
render() {
const {date} = this.state;
const values = {date}
return(
<Fragment>
<label id="form-name">Name: </label>
<input
type="text"
name="name"
id="input-name"
onChange={this.handleChange}
/>
{other values}
<Link to="/help" className="btn">next </Link>
</div>
</Fragment>
);
return(
<Help
{...this.state}
/>
)
}
}
Help.jsx
import React, {Component, Fragment} from 'react';
import { Link } from 'react-router-dom';
export class Help extends Component {
continue = () => {
window.print();
}
render() {
return(
<Fragment>
<p id="date">Date : {this.props.date}</p>
<p id="name">RECIEVED With thanks from {this.props.name}</p>
<Link to="/"><button id="btn-print" onClick={this.continue} value="Print"> Print</button></Link>
<button id="btn-back" onClick={this.goBack}>
Back
</button>
</Fragment>
)
}
}
export default Help;
Thank you for Your help
don't use class based component instead you can use functional component like this
const help = (props) => {
continue = () => {
window.print();
}
render() {
return(
<p id="date">Date : {props.date}</p>
<p id="name">RECIEVED With thanks from {props.name}</p>
<Link to="/"><button id="btn-print" onClick={this.continue} value="Print"> Print</button></Link>
<button id="btn-back" onClick={this.goBack}>
Back
</button>
</Fragment>
)
}
}

Dealing with bloated components in React

Can someone provide a clean example, or article dealing with bloated React code?
I have a HOC function on the main App.js file but I don't know how to "redeclare" the extended component to export. Then, the other components are not sharing the render. I already have Redux on one of the components called Counter. That is working.
App.js
import { connect } from 'react-redux'
import Counter from './components/Counter';
import Actions from './components/Actions';
function mapStateToProps(state) {
return {
countValue: state.count
};
}
//Action
var increaseAction = { type:"increase" }
var decreaseAction = { type:"decrease" }
// Map Redux actions to component props.
function mapDispachToProps(dispach) {
return {
// etc..
}
// The HOC
var connectedComponent = connect (
mapStateToProps,
mapDispachToProps
)(Counter);
export default connectedComponent;
Actions.js:
import React, {Component} from 'react';
import App from '../App';
import Counter from './Components/Counter';
import './App.css';
class Actions extends Component {
constructor(props) {
super(props);
this.state = {
response: ''
};
}
componentDidMount() {
fetch(
"/posts"
)
.then(response => response.json())
.then(data => this.setState({ response: data }))
}
render() {
return (
<div className="App">
<header className="App-header">
{/* <img src={logo} className="App-logo" alt="logo" /> */}
{Array.isArray(this.state.response) &&
this.state.response.map(resIndex => <div>
<ul>
<App>
`<Counter>`
<li>{resIndex.title} </li> // <- is this not bloated?
<li>{resIndex.author} </li>
</Counter>
</App>
</ul>
</div>
)}
</header>
</div>
)
}
}
export default Actions;

react - children component not showing

I'm trying to insert a child component inside another child component, but my code is not working. Following codes are the structure i'm trying to build.
const AddProductPage= () => {
return (
<PageTemplate>
<ProductTemplate>
<AddProduct />
</ProductTemplate>
</PageTemplate>
);
};
const PageTemplate= ({children}) => {
return (
<div className={cx('pagetemplate')}>
<HeaderContainer />
<main>
{children}
</main>
<Footer />
</div>
);
};
class ProductTemplate extends Component {
render() {
return (
<div className={cx('product-template')}>
...
<div className={cx('display')}>
{this.props.children}
</div>
</div>
);
}
}
class AddProduct extends Component {
render() {
return (
<div className={cx('addproduct')}>
addproduct
</div>
);
}
}
I'm trying to insert AddProduct component in ProductTemplate component as a child, which is inserted in PageTemplate component as a child. AddProductPage, however, is not showing AddProduct component. I'd be grateful if anyone can help.
I've run your code. May be you'r missing default export statements.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import AddProductPage from './AddProductPage';
ReactDOM.render(<AddProductPage />, document.getElementById('root'));
AddProductPage.js
import React from 'react';
import PageTemplate from './PageTemplate';
import ProductTemplate from './ProductTemplate';
import AddProduct from './AddProduct';
const AddProductPage= () => {
return (
<PageTemplate>
<ProductTemplate>
<AddProduct />
</ProductTemplate>
</PageTemplate>
);
};
export default AddProduct;
PageTemplate.js
import React from 'react';
const PageTemplate= ({children}) => {
return (
<div>
<main>
{children}
</main>
</div>
);
};
export default PageTemplate;
ProductTemplate.js
import React,{Component} from 'react';
class ProductTemplate extends Component {
render() {
return (
<div>
<div>
{this.props.children}
</div>
</div>
);
};
};
export default ProductTemplate;
AddProduct.js
import React, {Component} from 'react';
class AddProduct extends Component {
render() {
return (
<div>
addproduct
</div>
);
};
};
export default AddProduct;
Output is this :
addproduct
Here`s a Fiddle of your code
Works Fine!. I have removed cx API. I suppose the problem might be with className resolution. Check in the dom hierarchy weather the Children DOM Node exists and they have received their respective classnames.
const PageTemplate= ({children}) => {
return (
<div className={'pagetemplate'}>
<HeaderContainer />
<main>
{children}
</main>
<Footer />
</div>
);
};

React - fetched data isn't displayed

could anyone tell me why is that won't work? Proper data is displaying in the console (console.log(this.state);), but it won't be transfered to MainContainer.
Same data initialized in the constructor>state>users working without issues. Where's the problem?
App
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import Header from './components/header/Header';
import MainContainer from './containers/main-container/MainContainer';
class App extends Component {
constructor(props) {
super(props);
this.state = {
users: []
}
}
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(users => {
let u = users.map((user) => {
return {id: user.id, name: user.name, email: user.email}
})
return u;
})
.then(u => {
this.setState({users: u});
console.log(this.state);
});
}
render() {
return (
<div className="App">
<Header/>
<MainContainer users={this.state.users}/>
</div>
)
}
}
export default App;
MainContainer
import React from 'react';
import ActionBar from '../../components/action-bar/ActionBar'
import ListHeader from '../../components/list-header/ListHeader'
import ListItem from '../../components/list-item/ListItem'
import ListItemPlaceholder from '../../components/list-item-placeholder/ListItemPlaceholder'
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
users : props.users
}
}
render() {
const list = this.state.users.map(
(user) =>
{
const liStyle = {
'background-color': user % 2 == 0 ? '#fbfcfc' : 'transparent',
};
return <ListItem key={user.id} style={liStyle} id={user.id} name={user.name} email={user.email}/>
}
);
return (
<div className={'main-container'}>
<ActionBar />
<ListHeader />
{list}
</div>
)
}
}
export default MainContainer;
.................................................................................................................
Best Regards!
crova
In your <MainContainer> component you store the users in its state in the constructor but you never alter it. You only need to use state when the component needs to alter it during its lifetime. But the users come from it's parent via the users prop which you never render. So just render that prop instead:
const MainContainer = props => (
<div className="main-container">
<ActionBar />
<ListHeader />
{props.users.map(({id, name, email}) => (
<ListItem
key={id}
style={{
backgroundColor: id % 2 === 0 ? '#fbfcfc' : 'transparent'
}}
id={id}
name={name}
email={email}
/>
))}
</div>
);
When the users change in the parent it will re-render and pass the new users array to the <MainContainer>.
Also note that if your component only renders props and has no own state it can be written as a stateless functional component.

Resources