How to use map on multi objects array in React - reactjs

This is child component as i can you Props here
Child Component:
import React from "react";
const PeopleList = props => {
console.log("child Props :", props.data);
const list = props.data.map(item => item.name);
return <React.Fragment>{"list"}</React.Fragment>;
};
export default PeopleList;
Main Component:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchPeople } from "../actions/peopleaction";
import PeopleName from "../containers/peopleName";
class Main extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
this.props.dispatch(fetchPeople());
}
render() {
const { Error, peoples } = this.props;
console.log("data", peoples);
return (
<div className="main">
{"helo"}
<PeopleName data={peoples.results} />
</div>
);
}
}
const mapStateToProps = state => {
return {
peoples: state.peoples.peoples,
error: state.peoples.error
};
};
export default connect(mapStateToProps)(Main);
If i iterate the props multi objects array i can face Map is not define issue;
I need to iterate the props.data multi objects array in child component and i get object from Redux store. once component loaded the redux store.
can you please some one help me on this.
you can find whole code below mentioned

Try this It works in your codesandbox.
{peoples.results && <PeopleName data={peoples.results} />}

Related

How to add additional api to a fetch component in React JS

There are 2 separate components that fetch data through api. The code below is for the first component and then there is another component that fetch other data of the same company through another api and the code of that one is exactly the same except the api link. How to fetch the data from the other api in this component so there is no need for 2 different components.
import React, { Component, Fragment } from 'react'
import axios from 'axios'
class CompanyProfile extends Component {
constructor(){
super();
this.state={
Company:[]
}
}
componentDidMount(){
axios.get('http://localhost:3000/link').then(response =>{
**/////////for example axios.get('http://localhost:3000/link2') added here.**
this.setState({Company:response.data});
});
}
render() {
const cp = this.state.Company;
const CompanyView = contact.map((cp,i)=>{
**/////then mapped here.**
return <div>
<p>{cp.name}</p>
<p>{cp.type}</p>
<p>...other data</p>
**//// and then displayed here <p>{cp.CompanyProducts.data}</p>**
</div>
});
return (
<div>
{CompanyView}
</div>
)
}
}
export default CompanyProfile
I am not sure about your question. We can use container and presentational components.
A container does data fetching and then renders its corresponding sub-component. That’s it.
Refactor the CompanyProfile component to a stateless presentational component. Pass the company data from the remote API server to it from the container component.
So that we can reuse the CompanyProfile component.
CompanyProfile.jsx:
import React, { Component } from 'react';
class CompanyProfile extends Component {
render() {
const { campany } = this.props;
const CompanyView = campany.map((cp, i) => {
return (
<div>
<p>{cp.name}</p>
<p>{cp.type}</p>
<p>...other data</p>
<p>{cp.CompanyProducts.data}</p>
</div>
);
});
return <div>{CompanyView}</div>;
}
}
export default CompanyProfile;
Parent1.tsx:
import React, { Component } from 'react';
import axios from 'axios';
import CompanyProfile from './CampanyProfile';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
company: [],
};
}
componentDidMount() {
axios.get('http://localhost:3000/link').then((response) => {
this.setState({ company: response.data });
});
}
render() {
return <CompanyProfile company={this.state.company} />;
}
}
Parent2.jsx:
import React, { Component } from 'react';
import axios from 'axios';
import CompanyProfile from './CampanyProfile';
export default class Parent2 extends Component {
constructor(props) {
super(props);
this.state = {
company: [],
};
}
componentDidMount() {
axios.get('http://localhost:3000/link2').then((response) => {
this.setState({ company: response.data });
});
}
render() {
return <CompanyProfile company={this.state.company} />;
}
}

The data that comes from an API end point is undefined in the child component in React

Good day to all!
I have this situation: I use Apollo client to get data from a GraphQL API endpoint in the parent class component in React. I pass this data to the child class component. The first time everything works fine but after a page refresh the data in the child component becomes undefined and the app crashes.
Here is the representation of the situation:
The ParentComponent
import React, { Component } from 'react'
import { gql } from "apollo-boost";
import {graphql} from 'react-apollo';
import ChildComponent from './ChildComponent'
const getProducts = gql`
{
category {
products {
id
name
gallery
}
}
}
`
class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
products: []
}
}
componentDidMount() {
setTimeout(() => {
this.setState({
products: [...this.props.data.category.products]
})
}, 1000)
}
render () {
let products = this.state.products;
return (
<div><ChildComponent theProducts = {products}/></div>
)
}
}
export default graphql(getProducts)(ParentComponent);
The ChildComponent
import React, { Component } from 'react'
class ChildComponent extends Component {
constructor(props) {
super(props)
this.state = {
products: this.props.theProducts
}
}
render () {
let item = this.state.products.find(each => each.id === id);
return (
<div>
<ul>
<li>{item.name}</li>
<li><img src= {item.gallery[0]} alt="product"></img></li>
</ul>
</div>
)
}
}
export default ChildComponent;
So, when the app starts everything seems to work fine. But if I refresh the page it throws an error and says that name is undefined, gallery is undefined. It is clear that the data is not coming through to the ChildComponent. Is there a way to make sure that the data comes in at any time?
Thank you in advance.
You use theProducts in the ChildComponent but you pass theProduct from ParentComponent . And state product also has the same error. Just update to theProducts and product

what is best way to get props in React / React Native

I'm really regarding props in React/React-Native. I have a parent view. In this view I'm getting the user data from a LocalStorage.['
import React, { Component } from 'react';
import { Container, Content, View } from 'native-base';
import NutrionalToolbar from '../../components/NutrionalToolbar';
import { AsyncStorage } from 'react-native';
export default class LogsScreen extends Component {
state = {
user: '',
}
componentWillMount() {
this._bootstrapAsync();
}
_bootstrapAsync = async () => {
const user = await AsyncStorage.getItem('user');
this.setState({ user: JSON.parse(user) })
};
render() {
return (
<Container>
<NutrionalToolbar user={this.state.user} />
</Container>
);
}
}
Now inside the NutrionalToolbar component I have this.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
constructor(props) {
super(props)
console.log(this.props) // This renders an empty user object
}
render() {
console.log(this.props) // This renders the user object with values
return (
<View>
</View>
);
}
}
export default NutrionalToolbar;
How can I get this.props values inside the constructor. I'm getting the values inside render method. Why isn't working inside the constructor?
I would recommend looking into the componentDidUpdate lifecycle hook because, even if you could access the initial user prop in the constructor, you wouldn't be able to access updates to that prop in the constructor.
import React, { Component } from 'react';
import { View } from 'native-base';
class NutrionalToolbar extends Component {
componentDidUpdate() {
console.log(this.props) // This will always log the current props
}
render() {
return (<View></View>);
}
}
export default NutrionalToolbar;

react context with componentdidupdate

I am running a pattern like so, the assumption is that SearchResultsContainer is mounted and somewhere a searchbar sets the input.
class SearchResults {
render() {
return(
<ResultsContext.Consumer value={input}>
{input => <SearchResultsContainer input=input}
</ResultsContext.Consumer>
)
}
class SearchResultsContainer
componentDidUpdate() {
//fetch data based on new input
if (check if data is the same) {
this.setState({
data: fetchedData
})
}
}
}
this will invoke a double fetch whenever a new context value has been called, because componentDidUpdate() will fire and set the data. On a new input from the results context, it will invoke componentDidUpdate(), fetch, set data, then invoke componentDidUpdate(), and fetch, then will check if data is the same and stop the loop.
Is this the right way to be using context?
The solution I used is to transfer the context to the props through a High Order Component.
I have used this very usefull github answer https://github.com/facebook/react/issues/12397#issuecomment-374004053
The result looks Like this :
my-context.js :
import React from "react";
export const MyContext = React.createContext({ foo: 'bar' });
export const withMyContext = Element => {
return React.forwardRef((props, ref) => {
return (
<MyContext.Consumer>
{context => <Element myContext={context} {...props} ref={ref} />}
</MyContext.Consumer>
);
});
};
An other component that consumes the context :
import { withMyContext } from "./path/to/my-context";
class MyComponent extends Component {
componentDidUpdate(prevProps) {
const {myContext} = this.props
if(myContext.foo !== prevProps.myContext.foo){
this.doSomething()
}
}
}
export default withMyContext(MyComponent);
There must be a context producer somewhere :
<MyContext.Provider value={{ foo: this.state.foo }}>
<MyComponent />
</MyContext.Provider>
Here is a way to do it that doesn't require passing the context through props from a parent.
// Context.js
import { createContext } from 'react'
export const Context = createContext({ example: 'context data' })
// This helps keep track of the previous context state
export class OldContext {
constructor(context) {
this.currentContext = context
this.value = {...context}
}
update() {
this.value = {...this.currentContext}
}
isOutdated() {
return JSON.stringify(this.value) !== JSON.stringify(this.currentContext)
}
}
// ContextProvider.js
import React, { Component } from 'react'
import { Context } from './Context.js'
import { MyComponent } from './MyComponent.js'
export class ContextProvider extends Component {
render(){
return (
<MyContext.provider>
{/* No need to pass context into props */}
<MyComponent />
</MyContext.provider>
)
}
}
// MyComponent.js
import React, { Component } from 'react'
import { Context, OldContext } from './Context.js'
export class MyComponent extends Component {
static contextType = Context
componentDidMount() {
this.oldContext = new OldContext(this.context)
}
componentDidUpdate() {
// Do all checks before updating the oldContext value
if (this.context.example !== this.oldContext.value.example) {
console.log('"example" in context has changed!')
}
// Update the oldContext value if the context values have changed
if (this.oldContext.isOutdated()) {
this.oldContext.update()
}
}
render(){
return <p>{this.props.context.example}</p>
}
}
You could pass just the value that is changing separately as a prop.
<MyContext.Provider value={{ foo: this.state.foo }}>
<MyComponent propToWatch={this.state.bar}/>
</MyContext.Provider>
The extent -> props wrapper seems to a recommended by the react staff. However, they dont seem to address if its an issue to wrap context in a prop for an then consume the context directly from the child of the child, etc.
If you have many of these props you are needing to watch, especially when not just at the ends of branches for the component tree, look at Redux, its more powerful that the built in React.extent.

Export a dynamic array from a React component to another component

I built a react component that imports a Json file into an array to map the result. I need that array in another component. I don't know if I must built this component inside the new component or if there's a method to export the needed array (data). The array source is updated every 4 seconds.
Thanks for your help.
My first component is:
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class Ramas extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
const fetchData = () => {
axios
.get('http://localhost:8888/dp_8/fuente/procesos_arbol.json')
.then(({ data })=> {
this.setState({
data: data
});
console.log(data);
})
.catch(()=> {console.log('no recibido');});
};
fetchData();
this.update = setInterval(fetchData, 4000);
} // final componentDidMount
render() {
const initialData = this.state.data.map((el) => {
return (
<p>id={ el.id } | name - { el.name } | padre - {el.parent}</p>
);
});
return (<div className="datos_iniciales">
{ initialData }
</div>);
}
}
ReactDOM.render(
<Ramas />,
document.getElementById('container')
);
make one top level component that can contain the two components.
in the Ramas component ->
const updatedData = setInterval(fetchData, 4000);
this.props.datasource(updatedData);
write a new top level component ->
class TopComponent Extends React.Component{
state = {data: ''}
handleDataUpdate = (updatedData) => {
this.setState({data: updatedData});
}
render = () => {
<Ramas datasource={this.handleDataUpdate}>
<SecondComponent updatedData={this.state.data}>
</Ramas>
}
}
now from SecondComponent updatedData prop you can get the fresh data
By the way it is in ES7 syntax I wrote
If you have parent component, you should pass function from it to this component as a prop.
That function will than set state and data will flow one way as it's imagined with ReactJS.
For example instead of this.setState, you could call
this.props.jsonToArray
and in jsonToArray you should call setState which will pass data to that seccond component.

Resources