I am trying to view data using below sample. my list.js file as below:
import React, { Component } from 'react';
import { Person} from './Person';
export class List extends Component {
render() {
const persons = [
{
name:'Frank',
age:30,
city:'city 01'
},
{
name:'Hameed',
age:25,
city:'city 02'
},
{
name:'Jack',
age:24,
city:'city 03'
}
]
const personList = persons.map(person => <Person person={person}/>)
return <div> {personList} </div>
}
}
My person.js file is as below:
import React, { Component } from 'react';
export function Person (person){
return (
<div>
{person.name}
</div>
);
}
I need to print my array value inside the HTML but still did not render the view. I could not fix this.
My App.js file as below:
import logo from './logo.svg';
import './App.css';
import { List} from './components/List'
function App() {
return (
<div className="App">
<List></List>
</div>
);
}
export default App;
You pass the prop person to each <Person />, but inside the <Person /> component you are not getting it well. Each prop you pass, is getting to the function under the props variable, Try this code:
import React, { Component } from 'react';
export function Person (props){
return (
<div>
{props.person.name}
</div>
);
}
Or, alternatively, using destructuring:
import React, { Component } from 'react';
export function Person ({ person }){
return (
<div>
{person.name}
</div>
);
}
In <Person /> component you wrongly used props, try instead as:
export function Person (props) {
const { person } = props
// ... rest
}
See the difference from Person (person) to Person ({ person }). In the explained solution the person is destructured from props.
person.js
import React, { Component } from 'react';
export const Person = (props) => {
return (
<div>
{props.person.name}
</div>
);
}
or,
import React, { Component } from 'react';
export function Person (props){
return (
<div>
{props.person.name}
</div>
);
}
Related
Hey all im looking for help. im having some trouble with passing data from one child component to another child component using the context api. But i get this typeError instead, i tried a few searches so far without much luck. if anyone can't point me in the right direction it would be much appreciated!
thanks
CurrencyProvider.js
import { React, Component} from 'react';
export const MContext = React.createContext('');
class CurrencyProvider extends Component {
constructor() {
super()
this.state = {
setinputValue: (value) => this.setState({ inputValue: value })
}
}
render() {
return (
<MContext.Provider value={this.state}>
{this.props.children}
</MContext.Provider>)
}
}
export default CurrencyProvider;
Dropdown.js
import { useQuery, gql } from "#apollo/client";
import { useState } from "react";
import './Dropdown.scss';
import { MContext } from "../CurrencyProvider";
const EXCHANGE_RATES = gql`
query GetExchangeRates {
rates(currency: "AUD") {
currency
rate
name
}
}
`;
function Dropdown() {
const [isToggled, setToggle] = useState(false);
const { data, loading, error } = useQuery(EXCHANGE_RATES);
if (loading) {
return <div>loading</div>;
}
if (error) {
return <div>{error}</div>;
}
return (
<div className="custom-dropdown">
<ul className={`dropdown-menu ${isToggled ? 'open':''}`}>
<li value="0" className="first-item" onClick={() => setToggle(!isToggled)} onKeyPress={() => setToggle(!isToggled)} tabIndex="0">Select Currency:</li>
{data.rates.map(({ currency, rate, name },index) => (
<MContext.Consumer>
{(context) => (
<li className="list-item" key={index} data={rate} tabIndex="0" onClick={()=>{context.setinputValue(rate)}}> <span>{name}: {currency}</span></li>
)}
</MContext.Consumer>
))}
</ul>
</div>
);
}
export default Dropdown;
Input.js
import './Input.scss';
import { MContext } from "../CurrencyProvider";
function Input() {
return(
<MContext.Consumer>
{(context) => (
<input value={context.state.inputValue} />
)}
</MContext.Consumer>
);
}
export default Input;
CurrencyContainer.js
import Dropdown from '../Dropdown/Dropdown';
import Input from '../Input/Input';
import './CurrencyContainer.scss';
import CurrencyProvider from '../CurrencyProvider';
function CurrencyContainer() {
return (
<div className='currency-container'>
<h1 >Select Items</h1>
<div className="currency-wrapper">
<CurrencyProvider>
<div><Input /></div>
<div><Dropdown /></div>
<div><Dropdown /></div>
</CurrencyProvider>
</div>
</div>
);
}
export default CurrencyContainer;
App.js
import logo from './logo.svg';
import './App.scss';
import { client } from "./ApolloClient/client";
import { ApolloProvider } from '#apollo/client';
import CurrencyContainer from './CurrencyContainer/CurrencyContainer';
function App() {
return (
<ApolloProvider client={client}>
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
<CurrencyContainer />
</div>
</ApolloProvider>
);
}
export default App;
Why don't you try placing something more in the likes of this in a separate file mcontext.context.jsx:
import { createContext } from "react";
const MContext = createContext('');
export default MContext;
Then you can import it and
get values by importing your newly created context, the useContext hook and adding something like this to the top of a functional component which is encapsulated inside a MContext.Provider node:
const val = useContext(MContext);
set values:
<MContext.Provider value={mcontextValue}>
</MContext.Provider>
All children inside your MContext.Provider node and their children will have access to your MContext value given you get it as I showed you in the 1st part of the answer.
Your React import is incorrect. Change it to:
import React, {Component} from 'react';
React is the default export, not a named export.
React package doesn't have a named import called React, it has a default import that people generally use React for, so you should change this line
import { React, Component } from 'react';
to this
import React, { Component } from 'react';
If you use React 17+, you don't need to import React from 'react'; anymore, you can remove any mentioning of React from your import, so your import will look like this
import { createContext } from 'react';
But you have to turn off the lint rules for this import in your .eslintrc.json file like so
{
"rules": {
...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
So my App.js is:
import React from 'react';
import './App.css';
import Card from './users/Card';
function App() {
return (
<div className="App">
<Card />
</div>
);
}
export default App;
And the Card.js:
import React, { Component } from "react";
class Card extends Component {
render() {
const people = ["name1", "name2", "name3"];
const peopleList = people.map(person => <p>{person}</p>);
return (
{peopleList}
);
}
}
export default Card;
I'm getting an error:
Objects are not valid as a React child (found: object with keys {peopleList}).
If you meant to render a collection of children, use an array instead.
What am I doing wrong? If I use the map function in the App.js it works fine.
Simply return peopleList;
Demo here
Use a fragment:
return <>{peopleList}</>;
Full code:
class Card extends Component {
render() {
const people = ["name1", "name2", "name3"];
const peopleList = people.map(person => <p>{person}</p>);
return <>{peopleList}</>;
}
}
Demo: CodeSandbox
I am trying to concat the data entered in text field passing data from another stateless component, using props. Not sure why it is not working.
I have created two components
app.js 2. title.js
Data entered in input field needs to concat the string every time and display dynamically using props.
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Home';
import Title from './Title';
class App extends Component {
constructor(props)
{
super(props);
this.state =
{
text : ' ',
collection: []
}
this.eventHandler = this.eventHandler.bind(this);
this.eventSubmit = this.eventSubmit.bind(this);
}
eventHandler(event)
{
this.setState(
{text:event.target.value}
)
}
eventSubmit(event)
{
this.setState(
{collection:this.state.collection.concat(this.state.text)}
)
}
render() {
return (
<div className="App">
<input type="text" onChange ={this.eventHandler} />
<p> {this.state.text} </p>
<input type="submit" onClick={this.eventSubmit} />
<title collection={this.state.collection} />
</div>
);
}
}
export default App;
Title.js
import React from 'react';
const title = (props) =>
{
return (
<div>
<h1> {this.props.collection.toString()} </h1>
<h1> hello </h1>
</div>
);
}
export default title;
setState is async and when you use this.state inside it, it might not re-render. Use function inside setState instead:
eventSubmit(event) {
this.setState((prevState, props) => ({
collection: prevState.collection.concat(prevState.text)
}));
}
See 3. setState() is async: https://codeburst.io/how-to-not-react-common-anti-patterns-and-gotchas-in-react-40141fe0dcd
Mutations are bad in general and can lead to side effects use spread operator(...) to copy prevState array instead.
eventSubmit(event) {
this.setState((prevState) => ({
collection: [...prevState.collection, prevState.text]
}));
}
That's how you append data in array and update the state
Instead of stateless component I have created class component and it worked. Can someone explain me why it didn't worked with stateless why it worked now.
App.js
<code>
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Home from './Home';
import Title from './Title';
import Collection from './Collection';
class App extends React.Component {
constructor(props)
{
super(props);
this.state =
{
text : ' ',
collection: []
}
this.eventHandler = this.eventHandler.bind(this);
this.eventSubmit = this.eventSubmit.bind(this);
}
eventHandler(event)
{
this.setState(
{text:event.target.value}
)
}
eventSubmit(event)
{
this.setState(
{collection:this.state.collection.concat(this.state.text)}
)
}
render() {
return (
<div className="App">
<h1> ramesh </h1>
<input type="text" onChange ={this.eventHandler} />
<p> {this.state.text} </p>
<input type="submit" onClick={this.eventSubmit} />
<title name ={this.state.collection} />
<Collection name={this.state.collection} />
</div>
);
}
}
export default App;
</code>
Collection.js
<code>
import React, {Component} from 'react';
class Collection extends React.Component
{
render()
{
return(
<div>
<h1> {this.props.name.toString()} </h1>
</div>
);
}
}
export default Collection;
</code>
for starting, i saw many questions which looks like mine on stackoverflow but i think i miss something, this is why i'm asking this question.
I have a Maincomponent in my app which add datas to my store using the action addDatas.
This part works, i can access to my store in the context and in the children of MainComponent with this.props.
But when i go to OtherComponent (which is a basic component where i just want to show all the datas collected in MainComponent) my store seems to be empty.
Can someone tells me what i'm doing wrong and what OtherComponent should looks like for access the datas i set in the store when i was using MainComponent.
Thanks.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer from './reducers'
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
reducers.js
import { ADD_DATAS } from '../constants';
const reminder = (action) => {
switch (action.type) {
case ADD_DATAS:
return {
datas: action.datas,
id: action.id
};
default:
return {
text: action.text,
id: action.id
};
}
}
const reminders = (state = [], action) => {
let reminders = null;
switch (action.type) {
case ADD_DATAS:
reminders = [...state, reminder(action)];
return reminders;
default:
return state;
}
}
export default reminders;
Action.js
import {ADD_DATAS} from '../constants';
// ADD_DATAS = 'ADD_DATAS' in constants
export const addDatas = (text, id) => {
const action = {
type: ADD_DATAS,
datas: text,
id: id
}
return action;
}
App.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import RouterComponent from '../Router/RouterComponent';
import OtherComponent from './OtherComponent';
import MainComponent from './MainComponent';
class App extends Component {
render() {
return (
<div className="container-fluid">
<div className="row">
<Sidebar />
<Router>
<RouterComponent>
<Switch>
<Route exact path="/oth" component={OtherComponent}/>
<Route exact path="/main" component={MainComponent}/>
<Route exact path="/" component={MainComponent}/>
</Switch>
</RouterComponent>
</Router>
</div>
</div>
);
}
}
export default App;
MainComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'
class MainComponent extends Component {
addDataStore(text, id){
this.props.addDatas(text, id)
}
render(){
return ( .... )
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({addDatas}, dispatch);
}
function mapStateToProps(state){
return {
reminders: state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);
OtherComponent.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
class OtherComponent extends Component {
render(){
console.log(this.props.reminders)
}
}
function mapStateToProps(state){
return {
reminders: state
}
}
export default connect(mapStateToProps)(OtherComponent);
Sidebar.js
import React, { Component } from 'react';
import '../css/sidebar.css';
export default class Sidebar extends Component {
render(){
return (
<nav className="col-2 col-md-2 sidebar">
<div className="sidebar-logo">
<a href="/main">
MainComponent
</div>
</a>
</div>
<ul >
<li >
<a href="/main" >
MainComponent
</a>
</li>
<li >
<a href="/oth" >
OtherComponent
</a>
</li>
</ul>
</nav>
)
}
}
To Understand this we first need to understand the below snippet
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);
we are passing mapStateToProps function to the connect method which we get from react-redux. So let's Understand how connect works and what it actually does
1. It calls your mapStateToProps function and passes the current value of (redux state/ redux store) to the function.
2. Then whatever value is returned by the mapStateToProps function after execution is passed down as props to the mainComponent(in your case).
So Since the child component for the main component is not having connect statement the props are not available to it.
You can make the redux state available as props by two was
1. Passing it down from main component as follows inside mainComponent.js render method we have
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'
class MainComponent extends Component {
addDataStore(text, id){
this.props.addDatas(text, id)
}
render(){
return (
<Child1 reminders={this.props.reminders}/*can be accessed as this.props.reminders*//>
<Child2 reminders={this.props.reminders}/*can be accessed as this.props.reminders*//>
)
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({addDatas}, dispatch);
}
function mapStateToProps(state){
return {
reminders: state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);
2.Another way to do this will be using connect Statement inside your child component as well
export default connect(mapStateToProps, mapDispatchToProps)(MainComponent);
class Child1 extends Component{
.....
}
function mapDispatchToProps(dispatch){
return bindActionCreators({addDatas}, dispatch);
}
function mapStateToProps(state){
return {
reminders: state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Child1);//need to change here must be same as className
You should connect your OtherComponent to redux store as well using connect HoC.
You need to connect other components with mapStateToProps and mapDispatchToProps functions as you do in MainComponents.js
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { addDatas } from '../actions'
class OtherComponent extends Component {
addDataStore(text, id) {
this.props.addDatas(text, id)
}
render() {
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ addDatas }, dispatch);
}
function mapStateToProps(state) {
return {
...state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(OtherComponent);
You would connect the otherComponent as well using connect HOC, in order to access the Store. Once you have a component connected the Store in the Hierarchy you can pass the data as props on to its children. However you do need to connect the top level component/s to store
import React, { Component } from 'react';
import { connect } from 'react-redux'
class OtherComponent extends Component {
render(){
console.log(this.props.reminders)
}
}
function mapStateToProps(state){
return {
reminders: state
}
}
export default connect(mapStateToProps)(OtherComponent);
Well,
my problem wasn't on my implementation of Redux but on the fact that i used href for navigate between my components.
The problem was that my Sidebar component wasn't in the Router component, then i had to save the history in the redux store and call history.push in my sidebar component with the history i saved before.
In all my components inside the router i added in the constructor:
constructor(props){
super(props);
...
this.props.addHistory(props.history);
}
addHistory add history if it doesn't already exist.
Then in my sidebar, i use the history in the store for use the push function:
for (var e in this.props.reminders){
if(this.props.reminders[e].history !== undefined ){
this.props.reminders[e].history.push('/oth');
}
}
I don't know if it's the cleanest way to do this, but it works.
I am practicing React native. When I compile the following program, I am getting Cannot read property 'props' of undefined error for Details.js. Kindly let me know as to what went wrong here.
Layout.js
import React, {Component} from 'react';
import Header from './Header';
import Details from './Details';
export default class Layout extends React.Component {
constructor(props){
super(props);
this.state = {
heading: "Welcome no-name guy!",
header: "I am your header",
footer: "I am your footer"
};
}
render() {
return (
<div>
<Header headerprop={this.state.header} />
<Details detailprop={this.state.heading} />
</div>
);
}
}
Details.js
import React from 'react';
const Details = (detailprop) => {
return (
<div className="heading-style">{this.props.detailprop}</div>
);
};
Details.bind(this);
export default Details;
Header.js
import React, {Component} from 'react';
export default class Header extends React.Component {
render(){
return(
<div>{this.props.headerprop}</div>
);
}
}
In functional components, the props are passed as the first parameter. So, you only need to do this:
const Details = (props) => {
return (
<div className="heading-style">{props.detailprop}</div>
);
};
If you know the prop that you want to handle you can destructure that prop:
const Details = ({ detailProp }) => {
return (
<div className="heading-style">{detailprop}</div>
);
};
Your component argument should be props:
const Details = (props) => {
return (
<div className="heading-style">{props.detailprop}</div>
);
};
It could be detailprop as you have (or anything for that matter) but you would then need to access the prop by the confusing call:
detailprop.detailprop
props is the idiomatic approach for React.
Details.js is a stateless functional react component. https://facebook.github.io/react/docs/components-and-props.html
It receives props as its argument. You don't need this here.
import React from 'react';
const Details = (props) => {
return (
<div className="heading-style">{props.detailprop}</div>
);
};
Details.bind(this); // you don't need this
export default Details;
Also, div elements will not work for react-native . Please refer react native docs https://facebook.github.io/react-native/