Having trouble rendering data in react component - reactjs

I'm trying to render the following the 'dogName' value of the following array to the browser, but it's coming up as 'undefined':
[
{
"id": 1,
"dogName": "bruce"
},
{
"id": 2,
"dogName": "borker"
},
{
"id": 3,
"dogName": "henry"
}
]
So, first of all, the data is pulled from a database and set in state in the parent component, where's it's passed as props to the child component 'DogNameList' (which I've trimmed down to just the relevant bits):
import React from 'react';
import './styles.css'
import DogList from './DogList'
import Dogue from './Dogue'
import axios from 'axios'
import DogNameList from './DogNameList'
class App extends React.Component {
constructor(){
super()
this.state = {
**dogName:[]**
}
}
componentDidMount() {
axios.get('http://localhost:3000/dogs')
.then(res => {
this.setState({
**dogName:res.data**
})
})
.catch(error => {
console.log(error)
})
}
render() {
return (
<div>
<DogNameList **names = {this.state.dogName}**/>
<Dogue/>
</div>
);
}
}
export default App;
In DogNameList, the data is mapped over and then passed as props to the 'Dogue' component (stupid names, I know, but this is a personal project):
import React from 'react'
import Dogue from './Dogue'
const DogNameList = (props) => {
return(
<div>
{
props.names.map(name => {
console.log(name.dogName)
return <Dogue name = {name} key ={name.id}/>
})
}
</div>
)
}
export default DogNameList
finally, it's supposed to be rendered to the browser via the 'Dogue' component:
import React from 'react'
import axios from 'axios'
class Dogue extends React.Component {
constructor(props){
super(props)
this.state = {
}
}
render(){
return (
<div>
<img className = 'img' src = {this.props.dogList}/>
<br/>
<form className = 'form'>
<input type = 'text' placeholder = 'Enter dog name'/>
<br/>
<button>Submit</button>
</form>
**<h2>dog name: {this.props.name}</h2>**
</div>
)
}
}
export default Dogue
Any ideas why it's not working? I console logged the following and it returned the list of names (not as strings, I should add):
props.names.map(name => {
console.log(name.dogName)

First of all, replace this
<h2>dog name: {this.props.name}</h2>
with this
<h2>dog name: {this.props.name.dogName}</h2>
because you are creating a component with object, so name property actually holds the object, not the name property of the object.
return <Dogue name = {name} key ={name.id}/>
You also don't declare somewhere this property
{this.props.dogList}
Also to handle the undefined error messages, do this
{this.state.dogName && <DogNameList names ={this.state.dogName}/>}

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

Stripe - how do I save card element in react?

I'm trying to save card details for use later.
I have generated the SetupIntent client secret
I'm trying to use confirm card setup.
I'm following the docs here for react.
The following line:
const cardElement = this.props.elements.getElement('card')
is throwing me this error:
TypeError: Cannot read property 'getElement' of undefined
Where am I going wrong? My code is below:
This is the relevant portion of the main component:
import React from "react";
import { Elements, StripeProvider } from "react-stripe-elements";
import SaveCardForm from "./SaveCardForm";
<StripeProvider
apiKey={process.env.REACT_APP_API_STRIPE_PUBLISH}
>
<Elements>
<SaveCardForm/>
</Elements>
</StripeProvider>
And this is the SaveCardForm component
import React, { Component } from "react";
import { Stripe, CardElement, injectStripe } from "react-stripe-elements";
import axios from "axios";
class SaveCardForm extends Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
submit = e => {
e.preventDefault()
const cardElement = this.props.elements.getElement('card');
axios.get(`${process.env.REACT_APP_API}/saveCardDetails`).then(res => {
console.log('res.data', res.data)
this.props.stripe.confirmCardSetup(res.data.client_secret, {
payment_method: {
card: cardElement,
},
}).then( confirmCardSetupRes => {
console.log('confirmCardSetupRes', confirmCardSetupRes)
})
})
}
render() {
return (
<div>
<CardElement />
<button onClick={this.submit}>
Bid For Tickets
</button>
</div>
);
}
}
export default injectStripe(SaveCardForm);
Given your components, there is no prop named elements passed into SaveCardForm. If it's access to CardElement you are after, use a ref which will give you a direct reference to that component e.g.
constructor(props) {
...
this.cardEl = React.createRef();
}
submit = e => {
...
const card = this.cardEl.current.<accessDomHere>;
this.props.stripe.confirmCardSetup(res.data.client_secret, {
payment_method: {
card
},
}).then(...)
}
render() {
...
<div>
<CardElement ref={this.cardEl} />
...
</div>
}
Switch out <accessDomHere> for whatever DOM query you need to perform to get the information you need. There may even be a React property or function you can access (I'm not familiar with the component).
I resolved this by updating to the latest version of react-stripe-elements.
There is an error in the versions before 5.1.0

Not sure if i'm using react context correcly

I've created a form in react and after some research i think that if you don't want to use an external library to manage the form, the context could be the best choice, expecially in my case where i've many nested component that compose it.
But, i'm not sure that putting a function inside my state is a good thing.
But let me give you some code:
configuration-context.js
import React from 'react'
export const ConfigurationContext = React.createContext();
ConfigurationPanel.jsx
import React, { Component } from 'react'
import { Header, Menu, Grid } from 'semantic-ui-react'
import ConfigurationSection from './ConfigurationSection.jsx'
import {ConfigurationContext} from './configuration-context.js'
class ConfigurationPanel extends Component {
constructor(props) {
super(props)
this.state = {
activeItem: '',
configuration: {
/* the configuration values */
banana: (data) => /* set the configuration values with the passed data */
}
}
}
handleItemClick = (e, { name }) => this.setState({ activeItem: name })
render() {
return (
<ConfigurationContext.Provider value={this.state.configuration}>
<Grid.Row centered style={{marginTop:'10vh'}}>
<Grid.Column width={15} >
<div className='configuration-panel'>
/* SOME BUGGED CODE */
<div className='configuration-section-group'>
{this.props.data.map((section, i) => <ConfigurationSection key={i} {...section} />)}
</div>
</div>
</Grid.Column>
</Grid.Row>
</ConfigurationContext.Provider>
)
}
}
ConfigurationItem.jsx
import React, { Component } from 'react'
import { Input, Dropdown, Radio } from 'semantic-ui-react'
import {ConfigurationContext} from './configuration-context.js'
class ConfigurationItem extends Component {
static contextType = ConfigurationContext
constructor(props) {
super(props)
}
handleChange = (e, data) => this.context.banana(data)
itemFromType = (item) =>{
switch (item.type) {
case "toggle":
return <div className='device-configuration-toggle-container'>
<label>{item.label}</label>
<Radio name={item.name} toggle className='device-configuration-toggle'onChange={this.handleChange} />
</div>
/* MORE BUGGED CODE BUT NOT INTERESTING*/
}
}
render() {
return this.itemFromType(this.props.item)
}
}
So, at the end i've a ConfigurationContext that is just a declaration, everything is inside the parent state.
The thing that i don't like is putting the banana function inside the state (it will have more logic that just logging it)
What do you think about it?
Any suggestion is appreciated.
Thanks
banana is just a regular function and you do not have to put it in the state, just do:
class ConfigurationPanel extends Component {
banana = data => console.log(data)
...
render() {
return (
<ConfigurationContext.Provider value={{banana}}>
...
}
After that you can use this.context.banana(data) as normal.

How to use map on multi objects array in React

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} />}

PropTypes are always wrong

App component - set data from data.json, send props to children components:
import React from 'react';
import axios from 'axios';
import { HeaderPanel, PostsPanel } from './index';
import './app.scss';
export default class App extends React.Component {
constructor() {
super();
this.state = {
userData: Object,
infoData: Object,
postsData: Object
};
}
componentDidMount() {
axios.get('./data.json')
.then(res => {
this.setState({
userData: res.data.userData,
infoData: res.data.infoData,
postsData: res.data.posts
});
});
}
render() {
return (
<div className="app">
<div>
<HeaderPanel
userData={this.state.userData}
infoData={this.state.infoData}
/>
</div>
<div className="posts">
<PostsPanel postsData={this.state.postsData} />
</div>
</div>
);
}
}
First-child, divide props to approporiate components, give me the error too:
import React from 'react';
import PropTypes from 'prop-types';
import {ModalContainer, ModalDialog} from 'react-modal-dialog';
import { TopFunctionPanel, TopDisplayData } from './topPanel';
import { MiddleFunctionPanel, MiddleDisplayData } from './middlePanel';
import './headerPanel.scss';
export default class HeaderPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
avatar: Object,
user: String,
city: String,
country: String,
like: Number,
following: Number,
followers: Number,
isOpen: false
};
this.setLike = this.setLike.bind(this);
this.setFollowers = this.setFollowers.bind(this);
this.toggleModalWindow = this.toggleModalWindow.bind(this);
}
componentWillReceiveProps(props) {
this.setState({
avatar : props.userData.avatar,
user: props.userData.user,
city: props.userData.city,
country: props.userData.country,
like : props.infoData.like,
following: props.infoData.following,
followers: props.infoData.followers,
});
}
setLike(val) {
this.setState({like: val});
}
setFollowers(val) {
this.setState({followers: val});
}
toggleModalWindow() {
this.setState({isOpen: !this.state.isOpen});
}
render() {
return (
<div className="headerPanel">
{
this.state.isOpen &&
<ModalContainer onClose={this.toggleModalWindow}>
<ModalDialog onClose={this.toggleModalWindow}>
<div className="modal">
<div>
<div><h1>You share:</h1></div>
</div>
<p>{window.location.href}</p>
</div>
</ModalDialog>
</ModalContainer>
}
<TopFunctionPanel
setLike={this.setLike}
like={this.state.like}
toggleModalWindow={this.toggleModalWindow}
/>
<TopDisplayData
avatar={this.state.avatar}
user={this.state.user}
city={this.state.city}
country={this.state.country}
/>
<MiddleDisplayData
like={this.state.like}
following={this.state.following}
followers={this.state.followers}
/>
<MiddleFunctionPanel
setFollowers={this.setFollowers}
followers={this.state.followers}
/>
</div>
);
}
}
HeaderPanel.propTypes = {
userData: PropTypes.object,
infoData: PropTypes.object
};
And grand-child. They give me this strange error too
import React from 'react';
import PropTypes from 'prop-types';
import './middlePanel.scss';
const DisplayData = ({ like, following, followers }) => {
return (
<div className="middleDisplayData">
<div>
<p>{like}</p>
<p>Liks</p>
</div>
<div>
<p>{following}</p>
<p>Following</p>
</div>
<div>
<p>{followers}</p>
<p>Followers</p>
</div>
</div>
);
};
export default DisplayData;
DisplayData.propTypes = {
like: PropTypes.number,
following: PropTypes.number,
followers: PropTypes.number
};
And I have a warning (console and jest gave me this):
warning.js:35 Warning: Failed prop type: Invalid prop like of type function supplied to DisplayData, expected number.
in DisplayData (created by HeaderPanel)
in HeaderPanel (created by App)
in div (created by App)
in div (created by App)
in App
I don't get it. My propTypes should be number (in grand-child component). But even if I change it to func, I have warning that it should be number. I know that with func I should to use .isRequire because of undefined, but here? I even have no idea what is wrong. I saw similar topics, but they's about func prop type (and as I understood adding .isRequire will help me) or some wrong spelling.
I updated my questione.
Hmm, it strange, but it looks like everything is ok. It looks like during sending props from one component to second they change they type. After render they are function and then consola show this warning. But in the end they change to number so, everything is ok.

Resources