The code was working before I made it into a function so I am trying to figure out what is the difference and how to fix it.
import React from 'react';
const Ninjas = ({list}) => {
const ninjaList = list.map( ninjan => {
return (
<div className="ninja" key={ninjaList.id}>
<div>Name : {ninjan.name}</div>
<div>Age: {ninjan.age}</div>
<div>Belt:{ninjan.belt}</div>
</div>
)
})
return(
<div className="ninja-list">
{ninjaList}
</div>
)
}
export default Ninjas
you should try it like this:
import React from 'react';
const Ninjas = ({list}) => {
const ninjaList = list.map( (ninjan , index)=> {
return (
<div className="ninja" key={index}>
<div>Name : {ninjan.name}</div>
<div>Age: {ninjan.age}</div>
<div>Belt:{ninjan.belt}</div>
</div>
)
})
return(
<div className="ninja-list">
{()=>ninjaList()}
</div>
)
}
export default Ninjas
You probably have a typo in this line:
<div className="ninja" key={ninjaList.id}>
You are referencing to the list not to the list element.
This is sample code.
const ninjan = [ { id: 1, name: 'adasdasdasd' },{ id: 2, name: '123' }] ;
const ninjaList = ninjan.map( (ninjan)=> {
return (
<div className="ninja" key={ninjan.id}>
<div>Name : {ninjan.name}</div>
<div>Id : {ninjan.id}</div>
</div>
)
})
return (
<div className="content">
{ Object.keys(ninjaList).length >0 &&
ninjaList
}
</div>
);
Related
I currently have the following code:
const Suggestions = ({ suggestions }) => {
return (
suggestions.map((suggestion, i) => <p key={i}>{suggestion}</p>)
)
}
But I somehow want to be able to render all of the p tags inside a div. So, my final code after the mapping would look something like:
<div className="suggestions">
<p>suggestion1</p>
<p>suggestion2</p>
...
</div>
So I tried something like this:
const Suggestions = ({ suggestions }) => {
return (
<div className="suggestions">
suggestions.map((suggestion, i) => <p key={i}>{suggestion}</p>)
</div>
)
}
But this says suggestions and i isn't defined. Why am I not able to access the prop inside my div element?
You need to wrap your map with curly braces:
const Suggestions = ({ suggestions }) => {
return (
<div className="suggestions">
{suggestions.map((suggestion, i) => <p key={i}>{suggestion}</p>)}
</div>
)
}
import React from 'react';
export const Suggestions = ({ suggestions }) => {
return (
<div className="suggestions">
{suggestions && suggestions.map((item, i) => (<p key={i}> {item} </p>))}
</div>
)
}
export const App = () => {
const list = ['test1', 'test2','test3'];
return (
<div className='App'>
<h1>Hello React.</h1>
<Suggestions suggestions={list} />
</div>
);
}
I have a component A, which displays contents of a component B conditionally. Component B is contains a list of items, and when one clicks one of the items in the list, a new layout is supposed to be fired up showing details of the item. When i try to pass the props to switch to a new layout on a component B list item, i get an error toggleSearchType is not a function . Any assistance or recommendation on what i might be doing wrong will be appreciated.
My index file looks like this :
const PatientSearch: React.FC<PatientSearchProps> = ({ closePanel }) => {
const { t } = useTranslation();
const [searchType, setSearchType] = useState<SearchTypes>(SearchTypes.BASIC);
const toggleSearchType = (searchType: SearchTypes) => {
setSearchType(searchType);
};
return (
<>
<Overlay header={t('addPatientToList', 'Add patient to list')} closePanel={closePanel}>
<div className="omrs-main-content">
{searchType === SearchTypes.BASIC ? (
<BasicSearch toggleSearchType={toggleSearchType} />
) : searchType === SearchTypes.ADVANCED ? (
<PatientScheduledVisits toggleSearchType={toggleSearchType} />
) : searchType === SearchTypes.SCHEDULED_VISITS ? (
<AdvancedSearch toggleSearchType={toggleSearchType} />
) : null}
</div>
</Overlay>
</>
);
};
The searchtypes are as below :
export enum SearchTypes {
BASIC = 'basic',
ADVANCED = 'advanced',
SCHEDULED_VISITS = 'scheduled-visits'
}
My component A looks like this :
import React, { useEffect, useMemo, useState } from 'react';
interface BasicSearchProps {
toggleSearchType: (searchMode: SearchTypes) => void;
}
const BasicSearch: React.FC<BasicSearchProps> = ({ toggleSearchType }) => {
const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState('');
const [searchResults, setSearchResults] = useState<any>(null);
const customRepresentation = '';
return (
<div className={searchResults?.length ? styles.lightBackground : styles.resultsContainer}>
{searchResults?.length ? (
<div className={styles.resultsContainer}>{<SearchResults toggleSearchType={searchResults} patients={searchResults} />}</div>
) : (
<div>
<div className={styles['text-divider']}>{t('or', 'Or')}</div>
<div className={styles.buttonContainer}>
<Button
kind="ghost"
iconDescription="Advanced search"
renderIcon={Search16}
onClick={() => toggleSearchType(SearchTypes.ADVANCED)}>
{t('advancedSearch', 'Advanced search')}
</Button>
</div>
</div>
)}
</div>
);
};
export default BasicSearch;
Component B looks like this :
interface SearchResultsProps {
patients: Array<any>;
hidePanel?: any;
toggleSearchType: (searchMode: SearchTypes) => void;
}
function SearchResults({ patients, toggleSearchType }: SearchResultsProps ) {
const fhirPatients = useMemo(() => {
return patients.map((patient) => {
const preferredAddress = patient.person.addresses?.find((address) => address.preferred);
});
}, [patients]);
return (
<>
{fhirPatients.map((patient) => (
<div key={patient.id} className={styles.patientChart} onClick={() => toggleSearchType(SearchTypes.SCHEDULED_VISITS)} >
<div className={styles.container}>
<ExtensionSlot
extensionSlotName="patient-header-slot"
state={{
patient,
patientUuid: patient.id,
// onClick: onClickSearchResult,
}}
/>
</div>
</div>
))}
</>
);
}
}
I am currently working on an app using Firebase (Realtime Database) and ReactJS. I have the following :
I'd like to check in sellersList for values that are true. For each value that is true, i'd like to check into the sellers array for items containing the same value as the key from the first array in the "name : XXX" key-value pair.
Exemple : if i have "Nike" and "Puma" as true, i'd like to check in the sellers array for the items that have "Nike" and "Puma" as a name value, and return the whole parent objects (so i have access to the avatar, the link etc.).
Edit : here is my full component code :
import React, { Component } from 'react';
import Popup from '../Navbar/Popup';
import Upvote from './Upvote';
import actions from '../../actions';
import connectToStores from 'alt-utils/lib/connectToStores';
import ProductStore from '../../stores/ProductStore';
#connectToStores
class ProductPopup extends Component {
constructor(props) {
super(props);
this.state = {
sellers: [],
};
this.commentInput = React.createRef();
this.handleCommentButton = this.handleCommentButton.bind(this);
}
static getStores() {
return [ProductStore];
}
static getPropsFromStores() {
return ProductStore.getState();
}
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.status && this.props.status != nextProps.status) {
actions.getComments(this.props.pid);
}
return true;
}
renderHeader() {
return (
<header>
<section className="product-header-content">
<div className="product-header-thumb">
<img src={this.props.thumbnail} />
</div>
<div className="product-header-info">
<h1>{this.props.name}</h1>
<p>{this.props.tagline}</p>
</div>
</section>
</header>
);
}
renderContent() {
return (
<section className="product-container">
<div className="product-main">
<section className="product-infos_wrapper">
<section>
<img src={this.props.media} className="product-image" />
</section>
<section className="product-infos">
<p>{this.props.description}</p>
</section>
</section>
</div>
<div className="product-aside">
<div className="aside-btn">
<Upvote {...this.props} />
</div>
<div className="product-links-list">
<h3>Ou trouver la paire</h3>
<ul className="product-sellers">
{Object.keys(this.state.sellers)}
</ul>
</div>
</div>
</section>
);
}
handleComment = (e) => {
if (e.keyCode === 13 && e.target.value.length > 0) {
var comment = {
content: e.target.value,
name: this.props.user.name,
avatar: this.props.user.avatar,
};
actions.addComment(this.props.pid, comment);
e.target.value = null;
}
};
handleCommentButton() {
if (this.commentInput.current.value.length > 0) {
var comment = {
content: this.commentInput.current.value,
name: this.props.user.name,
avatar: this.props.user.avatar,
};
}
actions.addComment(this.props.pid, comment);
this.commentInput.current.value = null;
}
renderBodyDiscussion() {
return (
<section className="discussion">
<h2>Commentaires</h2>
{this.props.user ? (
<section className="post-comment">
<img src={this.props.user.avatar} className="medium-avatar" />
<input
placeholder="Que pensez-vous de ce produit ?"
onKeyUp={this.handleComment}
ref={this.commentInput}
/>
<button type="submit" className="btn btn-primary" onClick={this.handleCommentButton}>
Envoyer
</button>
</section>
) : null}
{this.renderComments()}
</section>
);
}
renderBody() {
return (
<section className="product-popup-body">
<main>{this.renderBodyDiscussion()}</main>
</section>
);
}
renderComments() {
return (
<ul className="comment-list">
{this.props.comments.map(function (comment, index) {
return (
<li key={index} className="comment-item">
<div className="comment-item_user">
<img src={comment.avatar} className="medium-avatar" />
<strong>{comment.name}</strong>
</div>
<section className="comment-item_content">
<p>{comment.content}</p>
</section>
</li>
);
})}
</ul>
);
}
render() {
const allSellers = Object.keys(this.props.sellersList).reduce((o, key) => {
this.props.sellersList[key] !== false && (o[key] = this.props.sellersList[key]);
this.state.sellers = o;
return o;
}, {});
console.log(this.props);
return (
<Popup {...this.props} style="product-popup">
{this.renderHeader()}
{this.renderContent()}
{this.renderBody()}
</Popup>
);
}
}
export default ProductPopup;
I think this might be what you're looking to do:
const sellers = [
{ avatar: "1", name: "Nike" },
{ avatar: "2", name: "Puma" },
{ avatar: "3", name: "Something" },
];
const sellersList = {
Nike: true,
Puma: true,
Something: false,
};
const includedSellers = Object.keys(sellersList).filter(
(brand) => sellersList[brand]
);
const results = sellers.reduce(
(results, seller) =>
includedSellers.includes(seller.name) ? [seller, ...results] : results,
[]
);
console.log(results);
//BETTER SOLUTION FROM #Drew Reese
const results2 = sellers.filter(({ name }) => includedSellers.includes(name));
console.log(results2);
This will give you an array of objects from the sellers array, where seller.name is a property from sellersList with a truthy value.
EDIT: As #Drew Reese pointed out, you can achieve this with just filter:
const results = sellers.filter(seller => includedSellers.includes(seller.name));
you have to avoid mutate the state manually like this:
this.state.sellers = o; //
https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
I currently have 4 buttons and 4 circles with 4 numbers each. When someone clicks button 1, circle 1 would be selected. When they click button 2, circle 2 would be selected. I currently have this:
class App extends Component {
constructor() {
super();
this.state = {
selButtonIdx: 1,
};
}
handleButtonSelection = (selButtonIdx) => {
this.setState({ selButtonIdx: selButtonIdx });
console.log(selButtonIdx);
};
render() {
return (
<div className="App">
<header className="App-header">Buttons</header>
<main>
<CircleSelector
selButtonIdx={this.state.selButtonIdx}
handleButtonSelection={this.handleButtonSelection}
/>
<Circles />
</main>
</div>
);
}
}
For my CircleSelector I have:
const CircleSelector = (props) => {
return (
<div className="CircleSelector">
{[1, 2, 3, 4].map((index) => (
<button
type="button"
onClick={() => props.handleButtonSelection(index)}
>
Select Button {index} {index === props.selButtonIdx && "(selected)"}
</button>
))}
</div>
);
};
and for circles:
const Circle = (props) => {
return (
<div className="Circles">
{[1, 2, 3, 4].map((index) => (
<div type="text">{index}</div>
))}
</div>
);
};
Yoou should integrate your circle and your button in the same component, this way you can simply use a reference to select the circle. I did the following example with input since i don't know what your circle contains but the idea is here :
import React, { Component } from "react";
import { render } from "react-dom";
const App = () => {
return (
<div>
{[1, 2, 3, 4].map(el => (
<MyComponent />
))}
</div>
);
};
const MyComponent = () => {
const elRef = React.createRef();
const selectElement = () => {
elRef.current.select(); // Select the content of the input
};
return (
<div>
<button onClick={selectElement}>Select element</button>
<input ref={elRef} type="text" value="element" />
</div>
);
};
render(<App />, document.getElementById("root"));
Here is the repro on stackblitz
I have the following array:
const elements = [
{
title: "foo"
section: <div>Foo <button onClick={sayHello}>Greet</button></div>
},
{
title: "bar"
section: <div>Bar <button onClick={sayHello}>Greet</button></div>
}
];
I want to render the component with something like:
const someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
...
render(){
return (
...
<div>
{someSections}
</div>
)
}
But I can't render them. The error is:
Uncaught Error: objects are not valid as a React child
Check the working solution:
const data = [
{
title: "foo",
section: <div>Foo <button>Greet</button></div>
},
{
title: "bar",
section: <div>Bar <button>Greet</button></div>
}
]
class App extends React.Component{
render(){
return(
<div>
{
data.map((item,i)=>{
return <div key={i}>{item.section}</div>
})
}
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
normally you would do something like this.
render(){
let someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
return (
<div>
{someSections}
</div>
)
}