so I have been trying to create dynamic menu in .net core + react environment
the problem I have been facing is basically this error message
Type '{}' is not assignable to type
'Readonly<RouteComponentProps<{}>>'.
Property 'match' is missing in type '{}'
Here is the code for
Layout.tsx
import * as React from 'react';
import { NavMenu } from './NavMenu';
export interface LayoutProps {
children?: React.ReactNode;
}
export class Layout extends React.Component<LayoutProps, NavMenu> {
public render() {
return <div className='container-fluid'>
<div className='row'>
<div className='col-sm-3'>
<NavMenu />
</div>
<div className='col-sm-9'>
{ this.props.children }
</div>
</div>
</div>;
}
}
the other file is NavMenu.tsx
import * as React from 'react';
import { Link, NavLink } from 'react-router-dom';
import { RouteComponentProps } from 'react-router';
import * as ReactDOM from 'react-dom';
interface navMenuItems {
menuItemsList: NavMenuPages[];
loading: boolean;
}
export class NavMenu extends React.Component<RouteComponentProps<{}>, navMenuItems> {
constructor() {
super();
this.state = { menuItemsList: [], loading: true };
fetch('api/Menu')
.then(response => response.json() as Promise<NavMenuPages[]>)
.then(data => {
this.setState({ menuItemsList: data, loading: false });
});
}
public render() {
this.renderMenu(this.state.menuItemsList);
return <div></div>;
}
public renderMenu(menuItemsList: NavMenuPages[]) {
return <div className='main-nav'>
<div className='navbar navbar-inverse'>
<div className='navbar-header'>
<button type='button' className='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
<span className='sr-only'>Toggle navigation</span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
<span className='icon-bar'></span>
</button>
<Link className='navbar-brand' to={'/'}>ReactCrudDemo</Link>
</div>
<div className='clearfix'></div>
<div className='navbar-collapse collapse'>
<ul className='nav navbar-nav'>
{menuItemsList.map(mil =>
<li>
<NavLink to={`${mil.toLink}`} exact activeClassName='active'>
<span className='glyphicon glyphicon-home'></span> {mil.name}
</NavLink>
</li>
)}
</ul>
</div>
</div>
</div>;
}
}
export class NavMenuPages{
name: string = "";
toLink: string = "";
isShown: boolean = true;
}
remaining files are the same as this tutorial:
https://www.c-sharpcorner.com/article/asp-net-core-crud-with-reactjs-and-entity-framework-core/
You are declaring NavMenu as requiring the RouteComponentProps<{}>, which it would normally receive automatically if you call it via <Route>, but you are calling it directly without passing the required props. Since NavMenu does not use any of the RouteComponentProps, you can just change the props type. Replace:
export class NavMenu extends React.Component<RouteComponentProps<{}>, navMenuItems>
with:
export class NavMenu extends React.Component<{}, navMenuItems>
Related
I tried console.log(this.state.bike). It gave me an array that basically contains everything I need. But when I try to access them I get undefined. How do I access the bikeLocation and bikeDescription? I have added 3 files. BikeServices, ListBikes and ViewBike Components.
import React, { Component } from 'react';
import BikeServices from '../services/BikeServices';
class viewBike extends Component {
constructor(props){
super(props)
this.state = {
bikeId: this.props.match.params.bikeId,
bike: {}
}
}
componentDidMount(){
BikeServices.getBikesById(this.state.bikeId).then( (res) => {
this.setState({bike: res.data});
//console.log(this.state.bike);
console.log(this.state.bike.bikeLocation);
});
}
render() {
return (
<div>
<br></br>
{this.state.bikeId}
<br></br>
{this.state.bike.bikeLocation}
</div>
);
}
}
export default viewBike;
//BikeServices
import axios from 'axios';
const BIKE_URL = `http://localhost:8090/api/v1/bikes`;
class BikeService{
getBikes(){
return axios.get(BIKE_URL);
}
getBikesById(bikeId){
return axios.get(BIKE_URL+ '/' +bikeId);
}
}
export default new BikeService();
//ListBikes component
import React, { Component } from 'react';
import BikeService from '../services/BikeServices'
class ListBikes extends Component {
constructor(props) {
super(props)
this.state = {
bikes : [],
}
this.viewBike = this.viewBike.bind(this);
}
// bikes=[]
componentDidMount(){
BikeService.getBikes().then((res) => {
this.setState({ bikes: res.data});
});
}
viewBike(bikeId){
console.log(this.props)
this.props.history.push(`/bike/${bikeId}`);
}
render() {
return (
<div className='container'>
{
this.state.bikes.map(
bike=>
<div className="card">
<div className="card-header">
<img src="https://c0.wallpaperflare.com/preview/483/210/436/car-green-4x4-jeep.jpg" alt="rover" />
</div>
<div className="card-body">
<span className="tag tag-teal">{bike.bikeStatus}</span>
<h4>
Bike Category: {bike.bikeCategory}
</h4>
<p>
Bike Description: {bike.bikeDescription}
<br></br>
Location:
{bike.location.address}, {bike.location.city}, {bike.location.state}, {bike.location.zip}
</p>
<button style={{marginLeft: "10px"}} onClick={() => this.viewBike(bike.bikeId)} className='btn btn-primary'>View</button>
<button>Rent</button>
</div>
</div>
)
}
</div>
);
}
}
export default ListBikes;
I tried console.log(this.state.bike). It gave me an array that basically contains everything I need. But when I try to access them I get undefined. How do I access the bikeLocation and bikeDescription? I have added 3 files. BikeServices, ListBikes and ViewBike Components.
Error: Type '{ children: Element; }' has no properties in common with
type 'IntrinsicAttributes & Pick<ClassAttributes & Props,
"ref" | "key">'.
I'm new learner of reactjs with typescript and I follow the https://www.youtube.com/watch?v=8jHKBAPNtpM tutorial for learning, but things are not explained properly on this video.
Can Anyone help me for resolve this issue.
My HomePage.tsx file
import React, { Component } from "react";
import Layout from "../../components/common/layout";
import Content from "../../components/common/content";
import Home from "./../../components/home";
class HomePage extends Component {
render() {
return (
<div className="wrapper">
<Layout>
<Content title="Dashboard">
<Home />
</Content>
</Layout>
</div>
);
}
}
export default HomePage;
my Layout.tsx file
import React, { Component } from "react";
import { connect } from "react-redux";
import TopNav from "../topnav";
import Aside from "../aside";
import UserStateInterface from "../../../interfaces/UserStateInterface";
import UserService from "../../../services/UserService";
import { setUser } from "./../../../store/actions";
interface Props {
user: UserStateInterface;
setUser: typeof setUser;
}
class Layout extends Component<Props> {
async componentDidMount() {
const response = await UserService.getCurrentUserProfile();
this.props.setUser(response);
}
render() {
return (
<React.Fragment>
<TopNav />
<Aside user={this.props.user} />
{this.props.children}
</React.Fragment>
);
}
}
const mapStateToProps = (state) => {
return {
user: state.user,
};
};
export default connect(mapStateToProps, { setUser })(Layout);
my Content.tsx file
import React, { Component } from "react";
interface Props {
title: String;
}
class Content extends Component<Props> {
render() {
const { title } = this.props;
return (
<div className="content-wrapper">
<section className="content-header">
<div className="container-fluid">
<div className="row mb-2">
<div className="col-sm-6">
<h1>{title}</h1>
</div>
<div className="col-sm-6">
<ol className="breadcrumb float-sm-right">
<li className="breadcrumb-item">
<a href="/" onClick={(event) => event.preventDefault()}>
Home
</a>
</li>
<li className="breadcrumb-item active">Blank Page</li>
</ol>
</div>
</div>
</div>
</section>
<section className="content">{this.props.children}</section>
</div>
);
}
}
export default Content;
my Home.tsx file
import React, { Component } from "react";
import Card from "./../common/card";
import TopCards from "./topcards";
import TodoWrapper from "../todo/todowrapper";
class Home extends Component {
render() {
return (
<React.Fragment>
<TopCards />
<div className="row">
<div className="col-md-6">
<TodoWrapper />
</div>
<div className="col-md-5">
<Card title="Some content will come" titleIcon="ion-clipboard">
<p>Content will come.</p>
</Card>
</div>
</div>
</React.Fragment>
);
}
}
export default Home;
You need to tell react that the component is ready to accept children.
React provides a utility for exactly this. Just replace your interface Props {...} with type Props = PropsWithChildren<{...}>.
import { PropsWithChildren } from "react";
type Props = PropsWithChildren<{
user: UserStateInterface;
setUser: typeof setUser;
}>;
Example: https://codesandbox.io/s/boring-chatelet-kp5vm?file=/src/Layout.tsx
I'm not getting props in my Nav component. Odd thing is, 'this.props.history.push' is working in my other components.
The same function is working in my other components, but when I try to call the push function, I'm getting 'err in logout TypeError: Cannot read property 'push' of undefined'. The 'this.props' object is logging as '{}'.
Any help is appreciated, thank you.
import React from 'react'
import logo from 'logo.png'
import css from './Nav.module.scss'
import { Link } from 'react-router-dom'
import Cookies from 'js-cookie'
import axios from 'axios'
class Nav extends React.Component {
constructor(props) {
super(props)
this.state = {
loggedIn: false
}
console.log(this.props)
}
_handleLogout = () => {
// const self = this
console.log(this.props)
axios.get('http://localhost:8080/logout', {
withCredentials: true
})
.then(res => {
console.log(res)
console.log('logout')
if (Cookies.get('sid') === undefined) {
this.props.history.push('/')
}
console.log(this.props)
})
.catch(err => {
console.log('err in logout', err)
})
}
render() {
return (
<div className={css.nav}>
<div className={css.leftPart}>
<Link to="/">
<div className={css.brandicon}>
<img src={logo} alt="Logo" />
</div>
<div className={css.brandname}>
somebrand
</div>
</Link>
</div>
<div className={css.rightPart}>
{
Cookies.get('sid') === undefined ?
<Link to="/login">
<div className={css.loginButton}>
Login
</div>
</Link>
:
<div className={css.logoutButton} onClick={this._handleLogout}>
Logout
</div>
}
</div>
</div>
)
}
}
export default Nav
My Nav component is only referenced once in my Layout component:
import React from 'react'
import Nav from 'components/Nav/Nav'
import css from './BasicLayout.module.scss'
class Basic extends React.Component {
render() {
return (
<div className={css.page}>
<Nav />
<div className={css.content}>
{this.props.children}
</div>
</div>
)
}
}
export default Basic
history and location are special props injected by React Router's HOC withRouter
import { withRouter } from 'react-router-dom'
class Nav extends React.Component{
render(){
const { history, location } = this.props
return <div>{`I'm at ${location.pathname}`}</div>
}
}
export default withRouter(Nav)
It works for functional components as well
export const Component = withRouter(({ history, location })) =>(
<div>{`I'm at ${location.pathname}`}</div>
)
I am having trouble rendering another component from my current component in vs code. The error message I get is..
Type '{}' is not assignable to type 'IntrinsicAttributes &
IntrinsicClassAttributes & Readonly<{ children?: ReactNode;
}> & ...'. Type '{}' is not assignable to type
'Readonly>'.
Property 'match' is missing in type '{}'.
Here is my code..
import * as React from 'react';
import { BillList } from './BillList';
import * as ReactDOM from "react-dom";
export interface BillComponentState {
children?: React.ReactNode,
bills: BillList
}
export class BillComponent extends React.Component<BillList>{
public render() {
return <div className='container-fluid'>
<div className='row'>
<div className='col-sm-3'>
<BillList />
</div>
<div className='col-sm-9'>
{this.props.children}
</div>
</div>
</div>;
}
}
Why can't I just render my BillList which is literally rendering a list of strings from a web api on my web server?
Disclaimer: I'm very new to React
EDIT: Here is the code in BillList.tsx
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
interface BillState {
bills: Bill[],
loading: boolean
}
export class BillList extends React.Component<RouteComponentProps<{}>, BillState>
{
constructor() {
super();
this.state = { bills: [], loading: true };
fetch("api/SampleData/GetBills")
.then(response => response.json() as Promise<Bill[]>)
.then(data => {
this.setState({
bills: data,
loading: false
});
});
}
public render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: BillList.renderBillsToList(this.state.bills);
return <div className="rendered-bills">
<h1>Bills to pay</h1>
{contents}
</div>
}
public static renderBillsToList(bills: Bill[]) {
return <ul>
{bills.map((bill, i) =>
<li key={i}> {bill.name} </li>
)}
</ul>;
}
}
interface Bill {
name: string;
}
Here is the code in a public repo. Let me know if you need more debugging information from me.
https://github.com/ddeamaral/billTracker
This code sample doesn't provide enough information to tell where the error originated from. However, the React.Component first parameter accepts the components properties and you seem to be passing on a component (BillList). Also there is a BillComponentState interface defined but never used and I don't see any actual component state.
Based on this code sample I can only advise you to rename BillComponentState to BillComponentProps and pass this to the component instead of BillList.
import * as React from 'react';
import { BillList } from './BillList';
import * as ReactDOM from "react-dom";
export interface BillComponentProps {
children?: React.ReactNode,
bills: BillList
}
export class BillComponent extends React.Component<BillComponentProps>{
public render() {
return <div className='container-fluid'>
<div className='row'>
<div className='col-sm-3'>
<BillList />
</div>
<div className='col-sm-9'>
{this.props.children}
</div>
</div>
</div>;
}
}
But this is just guessing since we don't know what BillList looks like.
I can declare a method within a constant, I try to implement the onLogout method in the navbar but I get an error in the method by saying 'js [;] expected' or require declaring the class in this way:
export default class Landing extends React.Component
import React from 'react';
import {Link} from 'react-router'
import { Accounts } from 'meteor/accounts-base';
const NavbarLanding = () => {
onLogout() {
Meteor.logout();
};
return (
<div className="navbar-landing">
<nav>
<div>
<ul className="ul-landing">
<img src="/images/fly_paper.svg"></img>
<li className="navbar-title"><a>Landing</a></li>
{/* <img border="0" height="40" hspace="0" src="/images/fly_paper.png" width="80" /> */}
{/* onClick={this.onLogout.bind(this) */}
{/* btn-primary */}
<div className="navbar-menu">
<li><a>acerca</a></li>
<li><a>portafolio</a></li>
<li><a>contacto</a></li>
<button className="btn"onClick={this.onLogout.bind(this)}>Logout</button>
</div>
</ul>
</div>
</nav>
</div>
);
};
export default NavbarLanding;
NavbarLanding.reactProptype = {
title: React.PropTypes.string.isRequired
};
You made an error declaring your component, it should be like this:
export default class NavbarLanding extends React.Component {
onLogout() {
Meteor.logout();
}
render() {
return (
// your html here
);
}
};
NavbarLanding.reactProptype = {
title: React.PropTypes.string.isRequired
};