Add functional component dynamical in react with out using class component - reactjs

I am trying to make a list of skills that are supposed to build in UI and I didn't have any problem in this step.
But when I add a new item to the list by writing it in input and clicking on a button to add it, the console sends a massage to tell: skills is not iterable.
this is a code in the App.js file:
import './App.css';
import Skills from './Components/Details'
import React,{useState} from 'react';
function App() {
const [numApp,reNumApp] = useState(0)
const [skill,reSkill] = useState('')
const [skills,reSkills] = useState(['HTML'])
const addSkill = (value)=>{
let newList = skills.push(value);
reSkills(newList);
console.log(skills);
}
console.log(skills)
return(
<>
<h1>Num Of applecation:{numApp}</h1>
<button onClick={()=>reNumApp(numApp + 1)}>Other Application</button>
<hr/>
<input type='text' value={skill} onChange={(e)=>reSkill(e.target.value)}/>
<button onClick={()=>{addSkill(skill)}}>Add</button>
<Skills skills = {skills}/>
</>
)
}
export default App;
And this is the code in the Details file:
import React,{useState,Fragment} from 'react';
function Skill({key,value})
{
const [count,reCount] = useState(0)
return(
<>
<span><p key={key}>{value} : {count}</p></span>
<button onClick={()=>reCount(count + 1)}>+</button>
</>
)
}
function Skills({skills}) {
return(
<Fragment>
{
[...skills].map((v,i)=>{return <Skill key={i} value={v}/>})
}
</Fragment>
)
}
export default Skills
I need to know how can I solve this problem without using the class component.

Try not to push on the current state, so change this:
let newList = skills.push(value);
reSkills(newList);
to this:
reSkills([...skills, value]);

Related

Push Object to Array UseState

I am learning ReactJs, and building a sample project. I am facing a problem while pushing the items to the array. My application has a list(10 items) and I am trying to push props to an array; But I am facing the below issues:
On click of "Choose" button, first time item does not push into the array, but it pushes on the second click.
When I click on the other li item the first item pushed to the array is deleted and the second item pushes to it.
I am trying to solve this for the last few hours, I tried other solutions on this platform but nothing works. What I am doing wrong.
import React, {useState} from 'react';
const MItem = (props)=>{
const [nameList, setName] = useState([]);
const NameHandler = ()=>{
setName(nameList => [...nameList, props]);
}
return (
<div>
<div>
<h3>{props.title}</h3>
<img src={props.pic} />
<p>{props.year}</p>
</div>
<div>
<button onClick={NameHandler}> Choose </button>
</div>
</div>
)
}
export default MItem;
Lets assume, you sent test using the attribute value as below
<MItem value="test">
Now you should use props.value not props
setName(nameList => [...nameList, props.value]);
Here is your example:
import React, {useState} from 'react';
const MItem = (props)=>{
const [nameList, setName] = useState([]);
const NameHandler = ()=>{
setName(nameList => [...nameList, props.value]);
}
return (
<button onClick={NameHandler}> Choose </button>
)
}
export default MItem;
More detail
you don't need to pass a function to setName you can just do.
Based on your comments
const NameHandler = ()=>{
const item = {title: props.title, pic: props.pic}
setName([...nameList, item]);
}

React render instagram feeds from data.json

I"m trying to render username comments with likes and a like. please see image on demo.
All of this comes form data.json
I can't find a way to display the json properly on the tags. What am I missing here?
Sorry I'm trying my best here with react as I'm quite a beginner.
demo
my index.js
import React from "react";
import styles from "./styles";
import { getCaptionFromEdges } from "./helpers";
const Posts = (props) => {
const { data } = props;
return (
<img src={data.owner.profile_pic_url} /> // this tag works
<p>{data.owner.node.username}</p> // this tag doesn't work
<hr>
//here I should display all comments with its like.
<p>{data.node.text}</p>// this doesn't work
);
};
export default Posts;
You need to wrap your elements with another element (or a Fragment). Try the following:
import React from "react";
import styles from "./styles";
import { getCaptionFromEdges } from "./helpers";
const Posts = (props) => {
const { data } = props;
return (
<>
<img src={data.owner.profile_pic_url} />
<p>{data.owner.node.username}</p>
<hr />
<p>{data.node.text}</p>
</>
);
};
export default Posts;

why is my component getting rendered once but then failing on refresh

i am working on small react assignment,
following is my component code. So my component is getting rendered once but then it just fails.i'll attach the screenshots too, can some one please explain what is happening?is there an error in the code or is it because of some rate limiting in API i am using?
import React from 'react'
const Menu = ({events}) => {
console.log(events);
return (
<div>
{events.map((event)=>{
return( <div key={event.category}>
<h3>{event.category}</h3>
</div>)
})}
</div>
)
}
export default Menu
code working image
error on same code pic
parent component code
import React,{useState,useEffect} from 'react';
import './App.css';
import Menu from './components/Menu';
function App() {
const [isLoading,setISLoading] = useState(true);
const[events,setEvents] = useState()
const getEvents = async()=>{
const response = await fetch('https://allevents.s3.amazonaws.com/tests/categories.json');
const eventsData =await response.json()
setISLoading(false);
setEvents(eventsData);
}
useEffect(()=>getEvents(),[]);
return (
isLoading?<h1>Loading...</h1>:<Menu events = {events}/>
);
}
export default App;
May be the parent component of Menu which is supplying events is not using any loading state. So when the component is mounted and starts making ajax calls, events is undefined. You need to put a condition over there like this:
import React from 'react'
const Menu = ({events}) => {
console.log(events);
return events ? (
<div>
{events.map((event)=>{
return( <div key={event.category}>
<h3>{event.category}</h3>
</div>)
})}
</div>
) : null
}
export default Menu

Learning React: Trouble understanding why my component won't render/ API/KEYS

I am fairly new to learning React and need some help.
I want to create a meal finder app using the MealDb API, my problem is it won't render.
Here is my code, in my app component:
import React, { useState } from 'react';
import './App.css';
import Search from './components/Search';
import Meals from './components/Meals';
import axios from 'axios';
function App() {
const [meals, setMeals] = useState({});
const searchMeals = async meals => {
const res = await axios.get(
`https://www.themealdb.com/api/json/v1/1/search.php?s=${meals}`
);
console.log(res.data);
setMeals({ meals: res.data });
};
return (
<div className='App'>
<Search searchMeals={searchMeals}></Search>
<Meals searchMeals={searchMeals} meals={meals}></Meals>
</div>
);
}
export default App;
I created a component Meals with this inside:
import React from 'react'
import MealsItem from './MealsItem'
const Meals = ({ meals}) => {
return (
<div >
{Object.keys(meals).map(meal=>(
<MealsItem key={meal.idMeal} meal={meal}/>
))}
</div>
);
};
export default Meals
and then for the rendering part I created a MealsItems component:
import React, { Fragment } from 'react';
const MealsItem = ({ meal :{strMealThumb, strMeal,}}) => {
return (
<Fragment>
<div id='result-heading'>
<h2>Search result for: {strMeal}</h2>
</div>
<div className='meal'>
<img src={strMealThumb} alt={strMeal} />
<div className='meal-info'>
<h3>{strMeal}</h3>
</div>
</div>
</Fragment>
);
};
export default MealsItem;
When I search something: I see a unique item with nothing in it. No title, no image. In the console when I inspect the app I read {meals: Array(8)} and "Warning: Each child in a list should have a unique "key" prop." I thought did write a unique key: key={meal.idMeal}.
EDIT: I did try to write
{meals.map(meal=>(
))}
to no avail, unfortunately. It gives me a type error meals.map is not a function.
This is the structure of the API:
{
"meals": [
{
"idMeal": "52772",
"strMeal": "Teriyaki Chicken Casserole",
"strDrinkAlternate": null,
"strCategory": "Chicken"
}
]
}
Edit # 2: This is what I get when I console.log(meals)
console.log(meals)
Thank you to anyone willing to help! Have a good day!
Reason is that you are using
Object.keys(meals).map.
Instead, do this
{meals.map(meal=>(
<MealsItem key={meal.idMeal} meal={meal}/>
))}
EDIT: Also set default value of meals state.
const [meals, setMeals] = useState([]); // dont use useState({})
Otherwise in the initial render before meals are fetched there will be error as we try to map over an object.

How to add {props.children} to a React component

i have many components which have {props.children} deeply nested inside.
considery DRY principle is there a way to add this using some React pattern.
example
let's say i have two components,
Comp1.js
import React from "react";
const Comp1 = props => {
return (
<div>
<h1>{props.children}</h1>
</div>
);
};
export default Comp1;
Comp2.js
import React from "react";
const Comp2 = props => {
return (
<div>
<div>
<h1>{props.children}</h1>
</div>
</div>
);
};
export default Comp2;
if you see above code we have both Comp1 and Comp2 have line of code {props.children} repeated inside.
what i want now is some function which will add this line of code, something like below,
const addPropsChildrenToComp = (Comp)=>{
return(
(props)=>{
///do somehting here
}
)
}
const Comp1 = props => {
return (
<div>
<h1></h1>
</div>
);
};
Comp1WithPropsChildren = addPropsChildrenToComp(Comp1)
using HOC doesn't work because, in HOC we never modify passed component.
anyway to aceve this.?
to get more idea of my problem see this demo: https://codesandbox.io/s/trusting-http-pd1yu
in there i woul like to see CompWithPropsChildren component render props.children inside it.
I think I see what you're trying to get to, and you can accomplish this just using another component.
import React from "react";
import ChildComp from "./ChildComp";
const Comp1 = props => {
return (
<div>
<ChildComp {...props} />
</div>
);
};
export default Comp1;
import React from "react";
const ChildComp = props => {
return <h1>{props.children}</h1>
}
Assuming your ChildComp has some complex logic you don't want to duplicate, this will make it reusable for you.

Resources