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
};
Related
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 am adding a props of sidebar Component to my template.
I am passing {...this.props} to Sidebar.
But it still leads to TypeError: Cannot read property 'map' of undefined in my Menu file.
My PostTemplateDetails file that I wish to add the Sidebar component:
import React from 'react'
import Sidebar from '../Sidebar'
import { Link } from 'gatsby'
import moment from 'moment'
import './style.scss'
class PostTemplateDetails extends React.Component {
render() {
const { subtitle, author } = this.props.data.site.siteMetadata
const post = this.props.data.markdownRemark
const tags = post.fields.tagSlugs
const tagsBlock = (
<div className="post-single__tags">
<ul className="post-single__tags-list">
{tags &&
tags.map((tag, i) => (
<li className="post-single__tags-list-item" key={tag}>
<Link to={tag} className="post-single__tags-list-item-link">
{post.frontmatter.tags[i]}
</Link>
</li>
))}
</ul>
</div>
)
return (
<div>
<Sidebar {...this.props} />
<div className="content">
<div className="content__inner">
<div className="post-single">
<div className="post-single__inner">
<h1 className="post-single__title">{post.frontmatter.title}</h1>
<div
className="post-single__body"
/* eslint-disable-next-line react/no-danger */
dangerouslySetInnerHTML={{ __html: post.html }}
/>
<div className="post-single__date">
<em>
Published {moment(post.frontmatter.date).format('D MMM YYYY')}
</em>
</div>
</div>
<div className="post-single__footer">
{tagsBlock}
<hr />
<p className="post-single__footer-text">
{subtitle}
<a
href={`https://twitter.com/${author.twitter}`}
target="_blank"
rel="noopener noreferrer"
>
<br /> <strong>{author.name}</strong> on Twitter
</a>
</p>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default PostTemplateDetails
My Sidebar component file:
import React from 'react'
import get from 'lodash/get'
import { Link } from 'gatsby'
import Menu from '../Menu'
import Links from '../Links'
import profilePic from '../../pages/photo.jpg'
import './style.scss'
class Sidebar extends React.Component {
render() {
const { location } = this.props
const {
author,
subtitle,
copyright,
menu,
} = this.props.data.site.siteMetadata
const isHomePage = get(location, 'pathname', '/') === '/'
/* eslint-disable jsx-a11y/img-redundant-alt */
const authorBlock = (
<div>
<Link to="/">
<img
src={profilePic}
className="sidebar__author-photo"
width="75"
height="75"
alt={author.name}
/>
</Link>
{isHomePage ? (
<h1 className="sidebar__author-title">
<Link className="sidebar__author-title-link" to="/">
{author.name}
</Link>
</h1>
) : (
<h2 className="sidebar__author-title">
<Link className="sidebar__author-title-link" to="/">
{author.name}
</Link>
</h2>
)}
<p className="sidebar__author-subtitle">{subtitle}</p>
</div>
)
/* eslint-enable jsx-a11y/img-redundant-alt */
return (
<div className="sidebar">
<div className="sidebar__inner">
<div className="sidebar__author">{authorBlock}</div>
<div>
<Menu data={menu} />
<Links data={author} />
<p className="sidebar__copyright">{copyright}</p>
</div>
</div>
</div>
)
}
}
export default Sidebar
My Menu component file, which is added in the Sidebar component file - this is where the error seems to be residing.
import React from 'react'
import { Link } from 'gatsby'
import './style.scss'
class Menu extends React.Component {
render() {
const menu = this.props.data
const menuBlock = (
<ul className="menu__list">
{menu.map(item => (
<li className="menu__list-item" key={item.path}>
<Link
to={item.path}
className="menu__list-item-link"
activeClassName="menu__list-item-link menu__list-item-link--active"
>
{item.label}
</Link>
</li>
))}
</ul>
)
return <nav className="menu">{menuBlock}</nav>
}
}
export default Menu
I am not sure why this is not working, since adding in my PAGETemplateDetails file seem to be working fine:
import React from 'react'
import Sidebar from '../Sidebar'
import './style.scss'
class PageTemplateDetails extends React.Component {
render() {
const page = this.props.data.markdownRemark
return (
<div>
<Sidebar {...this.props} />
<div className="content">
<div className="content__inner">
<div className="page">
<h1 className="page__title">{page.frontmatter.title}</h1>
<div
className="page__body"
/* eslint-disable-next-line react/no-danger */
dangerouslySetInnerHTML={{ __html: page.html }}
/>
</div>
</div>
</div>
</div>
)
}
}
export default PageTemplateDetails
SiteMetadata.menu is queried on the Post template File:
import React from 'react'
import Helmet from 'react-helmet'
import { graphql } from 'gatsby'
import Layout from '../components/Layout'
import PostTemplateDetails from '../components/PostTemplateDetails'
class PostTemplate extends React.Component {
render() {
const { title, subtitle } = this.props.data.site.siteMetadata
const post = this.props.data.markdownRemark
const { title: postTitle, description: postDescription } = post.frontmatter
const description = postDescription !== null ? postDescription : subtitle
return (
<Layout>
<div>
<Helmet>
<title>{`${postTitle} - ${title}`}</title>
<meta name="description" content={description} />
</Helmet>
<PostTemplateDetails {...this.props} />
</div>
</Layout>
)
}
}
export default PostTemplate
export const pageQuery = graphql`
query PostBySlug($slug: String!) {
site {
siteMetadata {
title
subtitle
copyright
author {
name
twitter
}
disqusShortname
url
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
html
fields {
tagSlugs
}
frontmatter {
title
tags
date
description
}
}
}
`
Not sure if this is relevant but this is the post file:
import React from 'react'
import { Link } from 'gatsby'
import moment from 'moment'
import './style.scss'
class Post extends React.Component {
render() {
const {
title,
date,
category,
description,
} = this.props.data.node.frontmatter
const { slug, categorySlug } = this.props.data.node.fields
return (
<div className="post">
<div className="post__meta">
<time
className="post__meta-time"
dateTime={moment(date).format('MMMM D, YYYY')}
>
{moment(date).format('MMMM YYYY')}
</time>
<span className="post__meta-divider" />
<span className="post__meta-category" key={categorySlug}>
<Link to={categorySlug} className="post__meta-category-link">
{category}
</Link>
</span>
</div>
<h2 className="post__title">
<Link className="post__title-link" to={slug}>
{title}
</Link>
</h2>
<p className="post__description">{description}</p>
<Link className="post__readmore" to={slug}>
Read
</Link>
</div>
)
}
}
export default Post
You're passing the property data as "menu" <Menu data={menu} />
In the Menu component, you don't have the menu property, you have this.props.data, which is equal to menu value, as defined in the Sidebar component. Probably there's no such property "menu" on this.props.data
So your code should be const data = this.props or const menu = this.props.data if you want to keep the variable name.
Thank you everyone, it was a query problem as ksav suspected. The Menu and Sidebar components were fine. I failed to query the menu information in my sitemetadata, and was able to fix it by going to my Post Template File and querying the menu, like so:
export const pageQuery = graphql`
query PostBySlug($slug: String!) {
site {
siteMetadata {
title
subtitle
copyright
menu {
label
path
}
author {
name
twitter
}
disqusShortname
url
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
html
fields {
tagSlugs
}
frontmatter {
title
tags
date
description
}
}
}
`
Thank you everyone, I'm struggling but I got there.
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>
I need to filter AssessmentCards by Year. I made the method.
But I need to call clickAllCards and clickYearCard method in onClick event on other file. How can I do that?
This is my code with the methods, I'm using Pug.JS to render:
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import messages from './messages';
import { getAssessmentsCards } from '../../functions';
import template from './index.pug';
const cardsAssessments = getAssessmentsCards();
export default class CardAssessment extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
constructor(props){
super(props);
this.state = {
listCards: [],
openCm: false,
}
}
componentWillMount(){
this.setState({listCards: cardsAssessments});
}
hover() {
this.setState({openCm: !this.state.openCm});
}
clickAllCards(e){
e.preventDefault();
this.setState({listCards: cardsAssessments});
}
clickYearCard(e){
e.preventDefault();
var filtered = cardsAssessments.filter((data) => {
return data.yearCard === '2018';
});
this.setState({listCards: filtered});
}
render() {
let cm = ["card-menu"];
if(this.state.openCm) {
cm.push('active');
}
return template.call(this, {
messages,
FormattedMessage,
Link,
cm
});
}
}
This is my pug file:
.card-adjust
div(href="" onClick="{this.clickYearCard.bind(this)}") 2018
div(href="" onClick="{this.clickAllCards.bind(this)}") All
Link.card.add-new(to="/add-assessment")
span
.add-icon
i.ti-plus
|
FormattedMessage(__jsx='{...messages.addAssessment}')
.card.card-materia(#for='data in this.state.listCards', key='{data.id}')
.card-body(id="{data.id}")
div(className="{cm.join(' ')}" onClick="{this.hover.bind(this)}")
i.fas.fa-ellipsis-v
.cm-floating
Link.cmf-agenda(to="/agendamento")
i.ti-agenda
|
FormattedMessage(__jsx='{...messages.scheduled}')
Link.cmf-copy(to="#")
i.pe-7s-copy-file
|
FormattedMessage(__jsx='{...messages.copy}')
Link.cmf-trash(to="#")
i.ti-trash
|
FormattedMessage(__jsx='{...messages.delete}')
.cm-icon
i(className='{data.icon}')
h2.cm-title {data.disciplineAbbreviation}
span.badge.badge-danger {data.status}
p.cm-questions {data.questionNumber}
FormattedMessage(__jsx='{...messages.questions}')
.cm-info
Link(to="#") {data.disciplineName}
Link(to="#") {data.year}
Link(to="#") {data.segment}
.cm-date
//- i.pe-7s-refresh-2
| {data.date}
And this is the file where I need to put the onClick event:
import React from 'react';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
import template from './index.pug';
import '../../assets/scss/main.scss';
export default function (params = {}) {
const { messages, FormattedMessage } = params;
return (
<div>
<ul className="nav nav-tabs">
<li className="nav-item">
<a className="nav-link" href="#">
<FormattedMessage {...messages.all} />
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">2018</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">2017</a>
</li>
</ul>
<div className="navigation-tabs display-none">
<a>
<i className="nt-icon ti-angle-left" />
</a>
1 de 3
<a>
<i className="nt-icon ti-angle-right" />
</a>
</div>
</div>
);
}
Thanks
You can pass any method for onClick event to any component like that:
App.js
class App extends React.Component {
handleClick = () => alert( "Clicked" );
render() {
return (
<div>
<Child click={this.handleClick}/>
</div>
)
}
}
or with a function component if you don't need lifecylce methods or "this" (here we don't need):
const App = () => {
const handleClick = () => alert( "Clicked" );
return (
<div>
<Child click={handleClick}/>
</div>
);
}
Child.js
const Child = ( props ) => (
<div>
<button onClick={props.click}>Click me!</button>
</div>
)
I am trying to implement the following: https://www.npmjs.com/package/react-sticky
in my code as follow:
import React from 'react';
import Video from './../video.jsx';
import Overview from './overview.jsx';
import Photography from './photography.jsx';
import Details from './details.jsx';
import Cast from './cast.jsx';
import porgectsCollection from './../../data/projectInfo.js';
import { StickyContainer, Sticky } from 'react-sticky';
class Nav extends React.Component {
constructor(props) {
super(props);
this.state = {
mobileMenu: false
};
}
showMobileMenu () {
this.setState({ mobileMenu: !this.state.mobileMenu });
}
render () {
let links = this.props.project.links.map(function(el, i){
return <li key={i}>{el}</li>;
});
const open = this.state.mobileMenu ? ' open' : '';
return (
<StickyContainer>
<span onClick={this.showMobileMenu.bind(this)} className="mobile-trigger">X</span>
<Sticky topOffset={100} stickyClassName="sticky-nav">
<nav className={"secondary-nav" + open}>
<ul>
{links}
</ul>
</nav>
</Sticky>
</StickyContainer>
);
}
}
class SingleProject extends React.Component {
getProjectDataFromUrl() {
return porgectsCollection.filter(el => el.title === this.props.params.id);
}
render () {
let data = this.getProjectDataFromUrl(),
project = data[0];
console.log(project);
return (
<section className="project-page">
<Video project={project} />
<Nav project={project} />
<Overview project={project} />
<Photography project={project} />
<Details project={project} />
<Cast project={project} />
</section>
);
}
}
export default SingleProject;
I would hope that when "Sticky" reached 100px from the top it would get a custom class "sticky-nav" applied to it. However the nav keeps on scrolling without getting stuck at all. I can see the divs applied around my markup with the extra padding but no more then that.
URL project: https://github.com/WebTerminator/aldemar,
file in question is singleProject.jsx
import React from 'react';
import Video from './../video.jsx';
import Overview from './overview.jsx';
import Photography from './photography.jsx';
import Details from './details.jsx';
import Cast from './cast.jsx';
import porgectsCollection from './../../data/projectInfo.js';
import { StickyContainer, Sticky } from 'react-sticky';
class Nav extends React.Component {
constructor(props) {
super(props);
this.state = {
mobileMenu: false
};
}
showMobileMenu () {
this.setState({ mobileMenu: !this.state.mobileMenu });
}
render () {
let links = this.props.project.links.map(function(el, i){
return <li key={i}>{el}</li>;
});
const open = this.state.mobileMenu ? ' open' : '';
return (
<Sticky stickyClassName="sticky-nav" topOffset={-100}>
<span onClick={this.showMobileMenu.bind(this)} className="mobile-trigger">X</span>
<nav className={"secondary-nav" + open}>
<ul>
{links}
</ul>
</nav>
</Sticky>
);
}
}
class SingleProject extends React.Component {
getProjectDataFromUrl() {
return porgectsCollection.filter(el => el.title === this.props.params.id);
}
render () {
let data = this.getProjectDataFromUrl(),
project = data[0];
return (
<section className="project-page">
<StickyContainer>
<Video project={project} />
<Nav project={project} />
<Overview project={project} />
<Photography project={project} />
<Details project={project} />
<Cast project={project} />
</StickyContainer>
</section>
);
}
}
export default SingleProject;