props are not working when using map method in react.js - javascript

props are passing fine when we are passing them as a whole array of objects but it is not working when I am passing the props by traversing through the array using map function.
import { React, useEffect, useState } from "react";
import axios from "axios";
import "./Home.css";
import Cardimg from "./Cardimg";
const Home = props => {
return (
<>
<div className="header">PHOTO GALLERY</div>
<div className="photos">
{props.data?.map(e => {
<Cardimg data={e.ImgUrl}></Cardimg>;
})}
</div>
</>
);
};
export default Home;
in the above code props are passing when I am passing manually in Cardimg component...but as soon as I start using map then it doesn't work...like the props are not reaching the component.
below is my Cardimg component
import React from 'react'
const Cardimg = (props) => {
console.log(props.data);
return (
<div>{props.data}</div>
)
}
export default Cardimg

You need to return the Cardimg component inside map callback function.
Either like this
{
props.data?.map(e => {
return <Cardimg data={e.ImgUrl}></Cardimg>;
});
}
Or like this
{
props.data?.map(e => <Cardimg data={e.ImgUrl}></Cardimg>)
}

Related

Error "Unexpected character '�'. (1:0)" when creact a higher order component in react

I'm beginner in react.js.
I'm tring to create my own higher order component.
But I have a problem.
enter image description here
my code:
withState.jsx:
import React from "react";
export function withState(component) {
const C = component;
return function (props) {
return <C {...props} extraProp="withState() is runing..." />;
};
}
Component file (Header.jsx):
import React from "react";
import { withState } from "./../HOFs/withState";
function Header(props) {
return (
<>
<h2>Header</h2>
<p>{JSON.stringify(props)}</p>
</>
);
}
export default withState(Header);

Reuse ReactJS component

I have built a ReactJS component for rendering emoction. Separate component can be built for each emoction, but I want to use one component but pass separate emoction as required.
This is what works so far:
emoction.js
import { faHeart } from "#fortawesome/free-solid-svg-icons";
import { faHeartBroken } from "#fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import React, { useState } from 'react';
const Emoction = () => {
return (
<FontAwesomeIcon icon={faHeart} />
);
};
export default Emoction;
emoction_hb.js
import { faHeart } from "#fortawesome/free-solid-svg-icons";
import { faHeartBroken } from "#fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import React, { useState } from 'react';
const EmoctionHb = () => {
return (
// <input type="text" />
<FontAwesomeIcon icon={faHeartBroken} />
);
};
export default EmoctionHb;
Now, I am bundling these two components as:
expanded_content.js
import Emoction from "../emoctions/emoctions";
import EmoctionHb from "../emoctions/emoctions_hb";
import styled from "#emotion/styled";
import { faHeartBroken } from "#fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import React, { Component } from 'react';
const Merged = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-start;
`;
const expandedContent = () => {
return(
<div>
<Merged>
<Emoction/>
<EmoctionHb/>
</Merged>
</div>
)
};
export default expandedContent;
which when I rendered using App.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import expandedContent from './components/merged_component/expanded_content'
class App extends React.Component {
render(){
return(
<Router>
<>
<Route path='/ExpandedContent' exact component={expandedContent}/>
</>
</Router>
)
}
}
export default App;
gives me.
What I am trying to do is that instead of creating a component called emoctions_hb.js I want to reuse emoction.js by passing "faHeartBroken" as the value in it.
If emoction.js is called without any value, I want it to use "faHeartBroken" as default value.
Tried following on to create Parent-Child relationship using https://webomnizz.com/change-parent-component-state-from-child-using-hooks-in-react/ but it did not work out for me.
Just pass the icon as a prop and set the default value to faHeartBroken:
const Emoction = ({ faIcon = faHeartBroken }) => {
return (
<FontAwesomeIcon icon={faIcon} />
);
};
It looks like you're importing useState but you're not implementing it anywhere. You could try implementing state in your expanded_content.js file and pass that down to your child component emoction.js, like this:
const ExpandedContent = () => {
const [heart, setHeart] = useState(true)
return(
<div>
<Emoction heart={heart} setHeart={setHeart}/>
</div>
)
};
export default ExpandedContent;
Notice that you will need to change the name of your component. See the docs here https://reactjs.org/docs/hooks-rules.html.
Then, inside of your Emoction component you will have access to heart which is set to true by default and you can also implement some logic to toggle the state using the function setHeart which is passed down from ExpandedContent:
const Emoction = ({heart, setHeart}) => {
const handleHearts = () => {
setHeart(heart => !heart)
}
return (
heart ? <FontAwesomeIcon icon={faHeart} /> : <FontAwesomeIcon icon={faHeartBroken} />
);
};
export default Emoction;
By using a ternary statement to return your component you can decide to show faHeart or faHeartBroken depending on the current state. All you need to do is add the functionality wherever you need it.

Error when passing a function in the React data

I am trying to pass a function on the sectionOne, then call sectionOne from another component but I am getting an error.
Error: Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
import React from 'react';
import {Home} from './home';
export const appTabBar = {
sectionOne: function sectionOne() {
return (
<>
<Home />
</>
);
},
};
import React from 'react';
import PropTypes from 'prop-types';
export const DrawerSection = props => {
const {sectionOne} = props;
return (
<>
<div>{sectionOne}</div>
</>
);
};
DrawerSection.propTypes = {
sectionOne: PropTypes.any,
};
You want to render sectionOne as a React component, and user-defined components must be capitalized. You can either rename sectionOne in the file where it is declared or assign it to a variable in the file where it is used:
export const DrawerSection = props => {
const {sectionOne: SectionOne} = props;
return (
<>
<div><SectionOne /></div>
</>
);
};

React hooks and context api localstorage on refresh

In my SPA, I am utilizing react hooks and context API. I need to persist the current state of the component view rendered using the context API so that I can implement the global component conditional rendering through the application.
I have two views on a single dashboard page: overview & detail. The button triggers the global state change and the view should be fixed on the state value even on page refresh.
Here's my code snippets:
AppRoutes file
import React, { useState } from "react";
import { Router, Route, Switch } from "react-router-dom";
import history from "../utils/history";
import { PyramidProvider } from "../context/pyramidContext";
import Dashboard from "../pages/dashboard/Dashboard";
const AppRoutes = () => {
return (
<div>
<React.Suspense fallback={<span>Loading...</span>}>
<Router history={history}>
<Switch>
<PyramidProvider>
<Route path="/" component={Dashboard} />
</PyramidProvider>
</Switch>
</Router>
</React.Suspense>
</div>
);
};
export default AppRoutes;
Dashboard page
import React, { useState, useEffect, useContext } from "react";
import { PyramidContext } from "../../context/pyramidContext";
import PyramidDetail from "../../components/pyramidUI/pyramidDetail";
import PyramidOverview from "../../components/pyramidUI/pyramidOverview";
const Dashboard = (props) => {
const { info, setInfo } = useContext(PyramidContext);
return (
<React.Fragment>
{info.uiname === "overview" ? <PyramidOverview /> : <PyramidDetail />}
</React.Fragment>
);
};
export default Dashboard;
Overview component
import React, { useState, useContext } from "react";
import { PyramidContext } from "../../context/pyramidContext";
const Overview = (props) => {
const { info, setInfo } = useContext(PyramidContext);
return (
<div className="d-flex flex-column dashboard_wrap">
<main>
<div className="d-flex">
<button
onClick={() => setInfo({ uiname: "detail", pyramidvalue: 1 })}
>
change view
</button>
</div>
</main>
</div>
);
};
export default Overview;
Detail component
import React, { useContext } from "react";
import { PyramidContext } from "../../context/pyramidContext";
// import axios from "axios";
const Detail = (props) => {
const { info, setInfo } = useContext(PyramidContext);
return (
<div className="d-flex flex-column dashboard_wrap">
<h2>Detail View</h2>
<div>
<button
type="button"
onClick={() => setInfo({ uiname: "overview", pyramidvalue: 0 })}
>
Back
</button>
</div>
</div>
);
};
export default Detail;
Context File
import React, { createContext, useEffect, useReducer } from "react";
let reducer = (info, newInfo) => {
return { ...info, ...newInfo };
};
const initialState = {
uiname: "overview",
pyramidvalue: 0,
};
const localState = JSON.parse(localStorage.getItem("pyramidcontent"));
const PyramidContext = createContext();
function PyramidProvider(props) {
const [info, setInfo] = useReducer(reducer, initialState || localState);
useEffect(() => {
localStorage.setItem("pyramidcontent", JSON.stringify(info));
}, [info]);
return (
<PyramidContext.Provider
value={{
info,
setInfo,
}}
>
{props.children}
</PyramidContext.Provider>
);
}
export { PyramidContext, PyramidProvider };
I click the button to render a detail view and soon as the page is refreshed, the component changes its view to overview instead of sticking around to detail. I checked the local storage values, and it is being updated properly, but still, the component view does not persist as per the value.
I am unable to understand where I am doing wrong, any help to resolve this issue, please? Thanks in advance.
You're never using the value of localStage in your info state,
you should replace your code with:
const [info, setInfo] = useReducer(reducer, localState || initialState);

Question around using useContext and useReducer hooks

I am trying to practice using hooks and i am not able to wrap my head around it.
I have a single component MessageBoard component that reads the data from state which just displays a simple list of messages.
I am passing down the dispatch and state via createContext so that the child components can consume it, which in-turn uses useContext in the child components to read the value.
When the page is refreshed, I expect to see the initial UI but it fails to render that the value in the context is undefined. I have already provided the initial state to the reducer when initializing it.
App.js
import React from "react";
import MessageBoard from "./MessageBoard";
import MessagesContext from "../context/MessagesContext";
function App() {
return (
<div>
<MessagesContext>
<h2>Reaction</h2>
<hr />
<MessageBoard />
</MessagesContext>
</div>
);
}
export default App;
MessageBoard.js
import React, { useContext } from "react";
import MessagesContext from "../context/MessagesContext";
function MessageBoard(props) {
const { state } = useContext(MessagesContext);
return (
<div>
{state.messages.map(message => {
return (
<div key={message.id}>
<h4>{new Date(message.timestamp).toLocaleDateString()}</h4>
<p>{message.text}</p>
<hr />
</div>
);
})}
</div>
);
}
export default MessageBoard;
MessagesContext.js
import React, { createContext, useReducer } from "react";
import reducer, { initialState } from "../state/reducer";
export default function MessagesContext(props) {
const Context = createContext(null);
const [state, dispatch] = useReducer(reducer, initialState);
return (
<Context.Provider
value={{
dispatch,
state
}}
>
{props.children}
</Context.Provider>
);
}
Broken Example - https://codesandbox.io/s/black-dust-13kj2
Instead if I change the MessagesContext file a bit and instead the Provider is directly injected into the App, it works as expected. Wondering what I have misunderstood here and what might be going on ?
MessagesContext.js
import { createContext } from "react";
export default createContext(null);
App.js
import React, { useReducer } from "react";
import reducer, { initialState } from "../state/reducer";
import PublishMessage from "./PublishMessage";
import MessageBoard from "./MessageBoard";
import MessagesContext from "../context/MessagesContext";
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<MessagesContext.Provider
value={{
dispatch,
state
}}
>
<h2>Reaction</h2>
<hr />
<PublishMessage />
<hr />
<MessageBoard />
</MessagesContext.Provider>
</div>
);
}
export default App;
Working Example - https://codesandbox.io/s/mystifying-meitner-vzhok
useContext accepts a context object (the value returned from React.createContext) and returns the current context value for that context.
const MyContext = createContext(null);
const value = useContext(MyContext);
// MessagesContext Not a contex object.
const { state } = useContext(MessagesContext);
In the first example:
// export the context.
export const Context = createContext(null);
export default function MessagesContext(props) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<Context.Provider
value={{
dispatch,
state
}}
>
{props.children}
</Context.Provider>
);
}
and then use it:
import { Context } from '../context/MessagesContext';
function MessageBoard() {
const { state } = useContext(Context);
...
}
Working broken example:

Categories

Resources