警告:功能无效,作为一个反应儿童。或如何将ID传递到路由标签中的元素

发布于 2025-02-10 19:56:00 字数 4740 浏览 1 评论 0原文

实际上,我试图渲染DishDetail组件,存在一个错误,例如“警告:功能无效,作为React Child”。因此,我无法在“/菜单/:cindid”下渲染DishDetail组件。

有人可以帮我吗?我试过谷歌搜索。 “ DishDetailComponent”和“ MainComponent”分别下面。多谢!

主组件:

import React, { Component, useContext} from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
 import { Routes, Route, Navigate, useParams} from 'react-router-dom';
import {connect} from 'react-redux';


const mapStateToProps = (state) => {
return {
    dishes: state.dishes,
    comments: state.comments,
    leaders: state.leaders,
    promotions: state.promotions
}}




class Main extends Component{
  constructor(props) {
   super(props);}

  render() {

const HomePage =() => {
    return(
        <Home 
        dish={this.props.dishes.filter((dish) => dish.featured)[0]}
        promotion={this.props.promotions.filter((promo) => promo.featured)[0]}
        leader={this.props.leaders.filter((leader) => leader.featured)[0]}
        />
    );
}

const DishWithId = ({match}) => {
    return(
        <DishDetail dish={this.props.dishes.filter((dish) => dish.id === parseInt(match.params.dishId, 10))[0]} 
        comments={this.props.comments.filter((comment) => comment.dishId === parseInt(match.params.dishId, 10))} 
        />

    );
  };  


return (
<div>
<Header/>
<Routes>
    <Route path ="/home" element={HomePage()} />
    <Route exact path="/menu" element={<Menu dishes={this.props.dishes} />} />
    <Route path='/menu/:dishId' element={<DishWithId />} />
    <Route exact path="/contactus" element={<Contact />} />
    <Route exact path="/aboutus" element={<About leaders={this.props.leaders}/>} />
    <Route path="*" element={<Navigate replace to="/home" />} />
</Routes>
<Footer />
</div>


);}}

export default connect(mapStateToProps)(Main);

DishDetailComponent:

import React from 'react'; 
import { Card, CardImg, CardText, CardBody, CardTitle , Breadcrumb, BreadcrumbItem} from 'reactstrap';

import { Link } from 'react-router-dom';

function RenderDish({dish}) {
    console.log('Menu Component render is invoked')
    return(
        <div className="col-12 col-md-5 m-1">
            <Card>
                <CardImg width="100%" object src={dish.image} alt={dish.name} />
                <CardBody>
                    <CardTitle>{dish.name}</CardTitle>
                    <CardText>{dish.description}</CardText>
                </CardBody>
            </Card>
        </div>
        
    );
}


function RenderComments({comments}) {
    const comment = comments.map((comment)=> {
        return (
            <div key={comment.id} className="col-12 col-md-5 m-1">
                
                <p>{comment.comment}</p>
                <p>--{comment.author} ,   {new Intl.DateTimeFormat('en-US', {year: 'numeric', month: 'long', day: '2-digit' }).format(new Date(comment.date))}</p>
            </div>
        )
    });
    return(
        <div className="col-12 col-md-5 m-1">
            <h4>Comment</h4>
            {comment}
        </div>
    );
}


const DishDetail = (props) => {
    if (props.dish != null) {
        return (
            <div className='container'>
            <div className='row'>
                <Breadcrumb>
                <BreadcrumbItem><Link to="/menu">Menu</Link></BreadcrumbItem>
                <BreadcrumbItem active>{props.dish.name}</BreadcrumbItem>
                </Breadcrumb>
                <div className='col-12'>
                    <h3>{props.dish.name}</h3>
                    <hr />
                </div>
            </div>
                <div className='row'>
                    
                    <div className="col-12 col-md-5 m-1">
                        <RenderDish dish={props.dish} />
                    </div>
                    <div className="col-12 col-md-5 m-1">
                        <RenderComments comments={props.comments} />
                    </div>
                </div>
            </div>
        );
    }
    else {
        return (
            <div></div>
        )
    }
} export default DishDetail;

    

Actually, I am trying to render the DishDetail component, there is an error like "Warning: Functions are not valid as a React child." Therefore, I cannot render the DishDetail Component under "/menu/:dishId".

Anyone can help me? I have tried googling it. The "DishDetailComponent" and "MainComponent" are below respectively. Thanks a lot!

The MainComponent:

import React, { Component, useContext} from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
 import { Routes, Route, Navigate, useParams} from 'react-router-dom';
import {connect} from 'react-redux';


const mapStateToProps = (state) => {
return {
    dishes: state.dishes,
    comments: state.comments,
    leaders: state.leaders,
    promotions: state.promotions
}}




class Main extends Component{
  constructor(props) {
   super(props);}

  render() {

const HomePage =() => {
    return(
        <Home 
        dish={this.props.dishes.filter((dish) => dish.featured)[0]}
        promotion={this.props.promotions.filter((promo) => promo.featured)[0]}
        leader={this.props.leaders.filter((leader) => leader.featured)[0]}
        />
    );
}

const DishWithId = ({match}) => {
    return(
        <DishDetail dish={this.props.dishes.filter((dish) => dish.id === parseInt(match.params.dishId, 10))[0]} 
        comments={this.props.comments.filter((comment) => comment.dishId === parseInt(match.params.dishId, 10))} 
        />

    );
  };  


return (
<div>
<Header/>
<Routes>
    <Route path ="/home" element={HomePage()} />
    <Route exact path="/menu" element={<Menu dishes={this.props.dishes} />} />
    <Route path='/menu/:dishId' element={<DishWithId />} />
    <Route exact path="/contactus" element={<Contact />} />
    <Route exact path="/aboutus" element={<About leaders={this.props.leaders}/>} />
    <Route path="*" element={<Navigate replace to="/home" />} />
</Routes>
<Footer />
</div>


);}}

export default connect(mapStateToProps)(Main);

The DishDetailComponent:

import React from 'react'; 
import { Card, CardImg, CardText, CardBody, CardTitle , Breadcrumb, BreadcrumbItem} from 'reactstrap';

import { Link } from 'react-router-dom';

function RenderDish({dish}) {
    console.log('Menu Component render is invoked')
    return(
        <div className="col-12 col-md-5 m-1">
            <Card>
                <CardImg width="100%" object src={dish.image} alt={dish.name} />
                <CardBody>
                    <CardTitle>{dish.name}</CardTitle>
                    <CardText>{dish.description}</CardText>
                </CardBody>
            </Card>
        </div>
        
    );
}


function RenderComments({comments}) {
    const comment = comments.map((comment)=> {
        return (
            <div key={comment.id} className="col-12 col-md-5 m-1">
                
                <p>{comment.comment}</p>
                <p>--{comment.author} ,   {new Intl.DateTimeFormat('en-US', {year: 'numeric', month: 'long', day: '2-digit' }).format(new Date(comment.date))}</p>
            </div>
        )
    });
    return(
        <div className="col-12 col-md-5 m-1">
            <h4>Comment</h4>
            {comment}
        </div>
    );
}


const DishDetail = (props) => {
    if (props.dish != null) {
        return (
            <div className='container'>
            <div className='row'>
                <Breadcrumb>
                <BreadcrumbItem><Link to="/menu">Menu</Link></BreadcrumbItem>
                <BreadcrumbItem active>{props.dish.name}</BreadcrumbItem>
                </Breadcrumb>
                <div className='col-12'>
                    <h3>{props.dish.name}</h3>
                    <hr />
                </div>
            </div>
                <div className='row'>
                    
                    <div className="col-12 col-md-5 m-1">
                        <RenderDish dish={props.dish} />
                    </div>
                    <div className="col-12 col-md-5 m-1">
                        <RenderComments comments={props.comments} />
                    </div>
                </div>
            </div>
        );
    }
    else {
        return (
            <div></div>
        )
    }
} export default DishDetail;

    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡水深流 2025-02-17 19:56:00

主页dishWithId是功能组件,因此在两种情况下,此都是不确定的。另外,您应该完全避免在其他反应组件中声明反应组件。他们应该自己在外面宣布。过滤应发生在父组件中,并且应将过滤结果作为道具传递给路由组件。

示例:

import React, { Component, useContext } from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
import { Routes, Route, Navigate, useParams } from 'react-router-dom';
import { connect } from 'react-redux';

const DishWithId = ({ dishes, comments }) => {
  const { dishId } = useParams();

  return (
    <DishDetail
      dish={dishes.find((dish) => String(dish.id) === dishId)} 
      comments={comments.find((comment) => String(comment.dishId) === dishId)} 
    />
  );
}; 

class Main extends Component{
  constructor(props) {
   super(props);
  }

  render() {
    return (
      <div>
        <Header/>
        <Routes>
          <Route
            path="/"
            element={(
              <Home 
                dish={this.props.dishes.find((dish) => dish.featured)}
                promotion={this.props.promotions.find((promo) => promo.featured)}
                leader={this.props.leaders.find((leader) => leader.featured)}
              />
            )}
          />
          <Route
            path="/menu"
            element={<Menu dishes={this.props.dishes} />}
          />
          <Route
            path='/menu/:dishId'
            element={(
              <DishWithId
                dishes={this.props.dishes}
                comments={this.props.comments}
              />
            )}
          />
          <Route path="/contactus" element={<Contact />} />
          <Route path="/aboutus" element={<About leaders={this.props.leaders}/>} />
          <Route path="*" element={<Navigate replace to="/home" />} />
        </Routes>
        <Footer />
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  dishes: state.dishes,
  comments: state.comments,
  leaders: state.leaders,
  promotions: state.promotions
});

export default connect(mapStateToProps)(Main);

最好放弃Connect hoc,并在需要访问状态的组件中直接使用use -elector挂钩。这避免了奇怪的道具钻探问题。

示例:

...

import React from 'react';
import { useSelector } from 'react-redux';

const Home = () => {
  const dishes = useSelector(state => state.dishes);
  const leaders = useSelector(state => state.leaders);
  const promotions = useSelector(state => state.promotions);

  const dish = dishes.find((dish) => dish.featured);
  const promotion = promotions.find((promo) => promo.featured);
  const leader = leaders.find((leader) => leader.featured);

  return .....;
};

组件

import React from 'react';
import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';

const DishDetail = () => {
  const { dishId } = useParams();
  const dishes = useSelector(state => state.dishes);
  const comments = useSelector(state => state.comments);

  const dish = dishes.find((dish) => String(dish.id) === dishId);
  const comments = comments.find((comment) => String(comment.dishId) === dishId);

  return <DishDetail {...{ comments, dish }} />;
};

其他路由

应用

import React, { Component, useContext } from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
import { Routes, Route, Navigate } from 'react-router-dom';

class Main extends Component{
  constructor(props) {
   super(props);
  }

  render() {
    return (
      <div>
        <Header/>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/menu" element={<Menu />}/>
          <Route path='/menu/:dishId' element={<DishWithId />}/>
          <Route path="/contactus" element={<Contact />} />
          <Route path="/aboutus" element={<About />} />
          <Route path="*" element={<Navigate replace to="/home" />} />
        </Routes>
        <Footer />
      </div>
    );
  }
}

export default Main;

HomePage and DishWithId are function components, so this is simply undefined in both cases. Also, you should completely avoid declaring React components within other React components. They should be declared outside on their own. The filtering should occur in the parent component and the filtered result should be passed as a prop to the routed component.

Example:

import React, { Component, useContext } from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
import { Routes, Route, Navigate, useParams } from 'react-router-dom';
import { connect } from 'react-redux';

const DishWithId = ({ dishes, comments }) => {
  const { dishId } = useParams();

  return (
    <DishDetail
      dish={dishes.find((dish) => String(dish.id) === dishId)} 
      comments={comments.find((comment) => String(comment.dishId) === dishId)} 
    />
  );
}; 

class Main extends Component{
  constructor(props) {
   super(props);
  }

  render() {
    return (
      <div>
        <Header/>
        <Routes>
          <Route
            path="/"
            element={(
              <Home 
                dish={this.props.dishes.find((dish) => dish.featured)}
                promotion={this.props.promotions.find((promo) => promo.featured)}
                leader={this.props.leaders.find((leader) => leader.featured)}
              />
            )}
          />
          <Route
            path="/menu"
            element={<Menu dishes={this.props.dishes} />}
          />
          <Route
            path='/menu/:dishId'
            element={(
              <DishWithId
                dishes={this.props.dishes}
                comments={this.props.comments}
              />
            )}
          />
          <Route path="/contactus" element={<Contact />} />
          <Route path="/aboutus" element={<About leaders={this.props.leaders}/>} />
          <Route path="*" element={<Navigate replace to="/home" />} />
        </Routes>
        <Footer />
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  dishes: state.dishes,
  comments: state.comments,
  leaders: state.leaders,
  promotions: state.promotions
});

export default connect(mapStateToProps)(Main);

It would be better to ditch the connect HOC and use the useSelector hook directly in the components that need to access the state. This avoid the odd props drilling issue.

Example:

Home

import React from 'react';
import { useSelector } from 'react-redux';

const Home = () => {
  const dishes = useSelector(state => state.dishes);
  const leaders = useSelector(state => state.leaders);
  const promotions = useSelector(state => state.promotions);

  const dish = dishes.find((dish) => dish.featured);
  const promotion = promotions.find((promo) => promo.featured);
  const leader = leaders.find((leader) => leader.featured);

  return .....;
};

DishDetail

import React from 'react';
import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';

const DishDetail = () => {
  const { dishId } = useParams();
  const dishes = useSelector(state => state.dishes);
  const comments = useSelector(state => state.comments);

  const dish = dishes.find((dish) => String(dish.id) === dishId);
  const comments = comments.find((comment) => String(comment.dishId) === dishId);

  return <DishDetail {...{ comments, dish }} />;
};

... etc for other routed components ...

App

import React, { Component, useContext } from 'react';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import Contact from "./ContactComponent";
import DishDetail from './DishdetailComponent';
import Header from './HeaderComponent';
import About from './AboutComponent';
import Footer from './FooterComponent';
import { Routes, Route, Navigate } from 'react-router-dom';

class Main extends Component{
  constructor(props) {
   super(props);
  }

  render() {
    return (
      <div>
        <Header/>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/menu" element={<Menu />}/>
          <Route path='/menu/:dishId' element={<DishWithId />}/>
          <Route path="/contactus" element={<Contact />} />
          <Route path="/aboutus" element={<About />} />
          <Route path="*" element={<Navigate replace to="/home" />} />
        </Routes>
        <Footer />
      </div>
    );
  }
}

export default Main;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文