Error when passing a function in the React data - javascript

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

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);

Can you interpolate path using react-router-dom v6 - ReactJS

I am aiming to create a custom path using react router dom v6 whereby my child component passes a string to my parent component (via a function) and then my parent component puts the strings value as a /param in the routes path parameter.
I have had success with all of this up to the last ste. I cannot figure out how to interpolate my dynamic value into the paths value (which is a string) the way you would interpolate a value into a regular string for example.
In a regular string I would just do Hello my URL is ${myurl} But this is does not work when trying to do it in the path value. Is there another way particular to react router dom v6 to accomplish my same goal (putting a dynamic string from my state into the parameters of path)?
Although this is just a exercise to see if its possible to do something like this (string interpolation in react router dom v6 route params), what I am trying to accomplish with this bit of code in the bigger picture is have my child component (which has buttons that can be clicked on, feed my parent component the name of the button that was clicked and then have the parent component (App.js) put the name of that button in the URL. That is why I have a state called myurl. I want the URL name to change based on the button clicked in the child component.
import logo from "./logo.svg";
import "./App.css";
import Genrenavbar from "./NavBars/Genrenavbar";
import { useState } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
function App() {
const [myurl, Setmyurl] = useState("");
console.log("My URL IS", myurl);
return (
<Router>
<Routes>
<Route path=`/${myurl}` element={<Genrenavbar Setmyurl={Setmyurl} />} />
</Routes>
</Router>
);
}
export default App;
Also below is my Genrenavbar component for reference
import React from "react";
import { useState, useEffect } from "react";
import useFetchgenrenavbar from "../utils/useFetchgenrenavbar";
import Moviedisplay from "./Moviedisplay";
import { useParams } from "react-router-dom";
export default function Genrenavbar({ Setmyurl }) {
const [mygenres, setMygenres] = useState({ genres: [] });
const [myselectedgenre, setMyselectedgenre] = useState({});
const mygottengenres = useFetchgenrenavbar();
useEffect(() => {
setMygenres(mygottengenres);
}, [mygottengenres]);
const help = mygenres.genres.map((elem) => console.log(elem.name));
const trending = "Trending";
const TopRated = "Top Rated";
const myuseeffectfunction = useEffect(
() => console.log("My selected genre is ", myselectedgenre.name),
[myselectedgenre]
);
return (
<div>
<h1>Hello</h1>
{mygenres.genres.map((elem) => (
<button
onClick={() => {
setMyselectedgenre(elem);
Setmyurl(elem.name);
}}
>
{elem.name}
</button>
))}
<Moviedisplay myselectedgenre={myselectedgenre} />
</div>
);
}
I don't think the myurl state in the parent component is necessary. Instead of trying to pass down a state updater function to the child component it can issue navigation actions to a route with a dynamic route param.
Example:
App
function App() {
return (
<Router>
<Routes>
... other routes ...
<Route path="/:genre" element={<Genrenavbar />} />
... other routes ...
</Routes>
</Router>
);
}
Genrenavbar
import { useNavigate } from 'react-router-dom';
export default function Genrenavbar() {
const navigate = useNavigate(); // <-- access navigate function
const [mygenres, setMygenres] = useState({ genres: [] });
const [myselectedgenre, setMyselectedgenre] = useState({});
const mygottengenres = useFetchgenrenavbar();
useEffect(() => {
setMygenres(mygottengenres);
}, [mygottengenres]);
const help = mygenres.genres.map((elem) => console.log(elem.name));
const trending = "Trending";
const TopRated = "Top Rated";
const myuseeffectfunction = useEffect(
() => console.log("My selected genre is ", myselectedgenre.name),
[myselectedgenre]
);
return (
<div>
<h1>Hello</h1>
{mygenres.genres.map((elem) => (
<button
onClick={() => {
setMyselectedgenre(elem);
navigate(`/${elem.name}`); // <-- navigate to genre
}}
>
{elem.name}
</button>
))}
<Moviedisplay myselectedgenre={myselectedgenre} />
</div>
);
}

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

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

Using React Hooks for Data Provider and Data Context

I am currently reworking my DataProvider, updating it from a class component to a functional component with React Hooks.
I believe my issue is in the way I am setting up my context consumer but I haven't found a good way to test this.
DataProvider.js
import React, { createContext } from "react";
const DataContext = createContext();
export const DataProvider = (props) => {
const [test, setTest] = React.useState("Hello");
return (
<DataContext.Provider value={test}>{props.children}</DataContext.Provider>
);
};
export const withContext = (Component) => {
return function DataContextComponent(props) {
return (
<DataContext.Consumer>
{(globalState) => <Component {...globalState} {...props} />}
</DataContext.Consumer>
);
};
};
So my withContext function should receive a component and pass it the props of the Context Provider.
I try to pull in my test state into a component.
import React from "react";
import style from "./DesktopAboutUs.module.css";
import { withContext } from "../../DataProvider";
const DesktopAboutUs = ({ test }) => {
return (
<div className={style.app}>
<div>{test}</div>
</div>
);
};
export default withContext(DesktopAboutUs);
No data is showing up for test. To me this indicates that my withContext function is not properly receiving props from the Provider.
Because you passed value={test}, globalState is a string, not an object with a test property.
Either of these solutions will result in what you expected:
Pass an object to the value prop of DataContext.Provider using value={{ test }} instead of value={test} if you intend globalState to contain multiple props.
Pass globalState to the test prop of Component using test={globalState} instead of {...globalState} if you do not intend globalState to contain multiple props.
const DataContext = React.createContext();
const DataProvider = (props) => {
const [test, setTest] = React.useState("Hello");
return (
<DataContext.Provider value={{ test }}>
{props.children}
</DataContext.Provider>
);
};
const withContext = (Component) => (props) => (
<DataContext.Consumer>
{(globalState) => <Component {...globalState} {...props} />}
</DataContext.Consumer>
);
const DesktopAboutUs = ({ test }) => (
<div>{test}</div>
);
const DesktopAboutUsWithContext = withContext(DesktopAboutUs);
ReactDOM.render(
<DataProvider>
<DesktopAboutUsWithContext />
</DataProvider>,
document.querySelector('main')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<main></main>

How to rewrite async HOC component to the React Hooks?

I'm using a template for my React app, and I came across one component that constantly gives me the following warning:
Warning: componentWillMount has been renamed, and is not recommended for use. See https:... for details.
Now, I'm trying to rewrite this component to React Hooks, to avoid multiple warnings in the console.
This is how the component looks like:
import React, { Component } from 'react';
import Nprogress from 'nprogress';
import ReactPlaceholder from 'react-placeholder';
import 'nprogress/nprogress.css';
import 'react-placeholder/lib/reactPlaceholder.css';
import CircularProgress from '../components/CircularProgress/index';
export default function asyncComponent(importComponent) {
class AsyncFunc extends Component {
constructor(props) {
super(props);
this.state = {
component: null,
};
}
componentWillMount() {
Nprogress.start();
}
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
Nprogress.done();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />,
});
}
}
render() {
const Component = this.state.component
|| (
<div
className="loader-view"
style={{ height: 'calc(100vh - 200px)' }}
>
<CircularProgress />
</div>
);
return (
<ReactPlaceholder type="text" rows={7} ready={Component !== null}>
{Component}
</ReactPlaceholder>
);
}
}
return AsyncFunc;
}
And here is the example of its usage:
import React from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import asyncComponent from '../util/asyncComponent';
const Routes = ({ match }) => (
<Switch>
<Route
path={`${match.url}/main`}
component={asyncComponent(() => import('./routes/MainPage/index'))}
/>
{/* <Route component={asyncComponent(() => import("app/routes/extraPages/routes/404"))}/> */}
</Switch>
);
export default withRouter(Routes);
I know how to rewrite component lifecycle methods (componentDidMount, componentWillUnmount should be rewritten to useEffect), but I don't understand part with props - asyncComponent gets importComponent as a prop, but where are we getting props in AsyncFunc? And how this could be rewritten to the functional component?
As I understood, asyncComponent is a Higher Order Component that responds with an updated component.
Sorry for not providing a sandbox for this example.
I couldn't test this code but I think is a solution
import React, { useState, useEffect } from 'react';
import Nprogress from 'nprogress';
import ReactPlaceholder from 'react-placeholder';
import 'nprogress/nprogress.css';
import 'react-placeholder/lib/reactPlaceholder.css';
import CircularProgress from '../components/CircularProgress/index';
const asyncComponent = importComponent => {
const [component, setComponent] = useState(null);
Nprogress.start();
useEffect(async () => {
const { default: Component } = await importComponent();
Nprogress.done();
setComponent(<Component {...importComponent} />);
}, []);
return component ? (
<ReactPlaceholder type="text" rows={7} ready>
{component}
</ReactPlaceholder>
) : (
<div className="loader-view" style={{ height: 'calc(100vh - 200px)' }}>
<CircularProgress />
</div>
);
};
export default asyncComponent;
I don't see the need to use the state mounted because you only use it in the dismount to setState component, but if 2 lines before you set mounted as true, it is not necessary to generate a re-render, you can go and setState component directly.
I hope this helps you.
According to reactjs.org, componentWillMount will not be supported in the future. https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
There is no need to use componentWillMount.
Before discussing your question but where are we getting props in AsyncFunc?
start with an example
const A = props => {
return <p>{JSON.stringify(props.location)}</p>;
};
function App() {
return (
<Switch>
<Route exact path="/" component={A} />
<Route exact path="/a" component={p => <A {...p} />} />
</Switch>
);
}
Route / and route /a both components are getting props but in different ways
on route / the props are automatically passed to the component
As you know HOC take a component and in response, it returns a component
so asyncComponent(() => import('./routes/MainPage/index') will return AsyncFunc
so we can simply say that
<Route
path={`${match.url}/main`}
component={AsyncFunc}
/>
and that's all
component={AsyncFunc} is equal to component={(p) => <AsyncFunc {...p} />}
and that how pros are passing

Categories

Resources