Meteor Put Collections Data in Divs - javascript

AddCategory.js
i want to display category on this page using function mydata().
data is printing in console .i want to bind all categories in divs using mydata() function.
import { Layout, Menu, Breadcrumb, Icon, Form, Input, Button} from 'antd';
const { SubMenu } = Menu;
const { Header, Content, Sider } = Layout;
import React from "react";
import { Link, Router, Route, IndexRoute, browserHistory } from "react-router";
import { createForm } from 'rc-form';
import { Category } from "../../../imports/collections/category-db";
const FormItem = Form.Item;
function hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
class AddCategory extends React.Component {
componentDidMount() {
// To disabled submit button at the beginning.
this.props.form.validateFields();
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
const category_name =values.categoryName;
Meteor.subscribe('category');
Meteor.call('categoryInsert',category_name);
alert('category added cheers !');
}
});
}
state = {
collapsed: false,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
mydata(){
Meteor.subscribe('category');
var categories = Category.find({}).fetch();
categories.forEach(function(cat){
console.log(cat.category_title);
});
}
render() {
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
// Only show error after a field is touched.
const userNameError = isFieldTouched('userName') && getFieldError('userName');
return (
<Layout>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<div className="logo" >
</div>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1">
<Link to="/users-admin"> <Icon type="user" />
<span> USERS </span></Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/category-admin">
<Icon type="video-camera" />
<span>Category</span>
</Link>
</Menu.Item>
<Menu.Item key="3">
<Icon type="mail" />
<span>Blogs 3</span>
</Menu.Item>
<Menu.Item key="4">
<Icon type="mail" />
<span>Jobs 4</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 720 }}>
<Form layout="inline" onSubmit={this.handleSubmit}>
<FormItem
validateStatus={userNameError ? 'error' : ''}
help={userNameError || ''}
>
{getFieldDecorator('categoryName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ fontSize: 13 }} />} placeholder="Category tile" />
)}
</FormItem>
<FormItem>
<Button
type="primary"
htmlType="submit"
disabled={hasErrors(getFieldsError())}
>
Log in
</Button>
</FormItem>
</Form>
{this.mydata()}
</Content>
</Layout>
</Layout>
);
}
}
export default createForm()(AddCategory);
Please suggest.

You just need to return an array of JSX div entries with individual 'key' attribute from your mydata() function, such as:
mydata(){
const data = [];
Meteor.subscribe('category');
var categories = Category.find({}).fetch();
categories.forEach(function(cat, index){
console.log(cat.category_title);
data.push(<div key={`data-${index}`}>{ cat.category_title }</div>);
});
return data;
}

Related

Material-ui Tab clicking submit to go to the next page removes the tab. How can I fix this?

I have these tabs to go to the next step. However, once clicking submits, this will go to the correct page, but this will also remove the tab. How can I fix this?
I have recreated this in codesandbox: https://codesandbox.io/s/dawn-cloud-uxfe97?file=/src/App.js
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography component="span">{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired
};
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`
};
}
const Ordering = () => {
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab
label="Step 1"
{...a11yProps(0)}
component={Link}
to={`/step1`}
/>
<Tab label="Step 2" {...a11yProps(1)} />
</Tabs>
</Box>
<TabPanel value={value} index={0}>
<Step1 />
</TabPanel>
<TabPanel value={value} index={1}>
<Step2 />
</TabPanel>
</div>
);
};
export default Ordering;
Step1.js
Navigating this to the step2 component does go to the next page, but this will also remove the tab
import { useNavigate } from "react-router-dom";
const Step1 = () => {
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
navigate("/Step2");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="submit" />
</form>
</div>
);
};
export default Step1;
Step2.js
const Step2 = () => {
return <div>Step2</div>;
};
export default Step2;
In your case you're not nesting your routes properly. So, For nested route you need to define a route inside another one. Refer this page https://reactrouter.com/docs/en/v6/api#routes-and-route for more information.
Getting back to your question. You need to update your code in two place. First how the routes are defined.
<Route path="/page" element={<Page />}>
<Route path="step1" element={<Step1 />} />
<Route path="step2" element={<Step2 />} />
</Route>
Once, your routes are updated. You are linking your panels based on route. So, you need not define them again in your Page component. You can remove those component from there and just add code so that when tab is click you change your navigation bar url. Sadly Tab of mui doesn't support component property https://mui.com/api/tab/ . You have to do that manually. You can use useNavigate provided by react router dom. Your updated Page component would look like this
I have added comment // This is added. To see where I've made changes. Just in 2 places changes are required.
import React, { useState, useEffect } from "react";
import { Box, Tab, Typography, Tabs } from "#mui/material";
import PropTypes from "prop-types";
import Step1 from "./Step1";
import Step2 from "./Step2";
import { Link } from "react";
// hook is imported
import { useNavigate } from "react-router-dom";
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography component="span">{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired
};
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`
};
}
const paths = ['/page/step1', '/page/step2']
const Ordering = () => {
const [value, setValue] = React.useState(0);
//This is added
const navigate = useNavigate()
const handleChange = (event, newValue) => {
setValue(newValue);
// This is added
navigate(paths[newValue])
};
return (
<div>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab
label="Step 1"
{...a11yProps(0)}
component={Link}
to={`/step1`}
/>
<Tab label="Step 2" {...a11yProps(1)} />
</Tabs>
</Box>
{/* Removed tab panels from here */}
</div>
);
};
export default Ordering;

Accessing functionality from parent component in child component ReactJS

I have working code in App.jsx. Everything is working when this written together in one file.
const App = props => {
const [cartProducts, setCartProducts] = useState([]);
const [products, setProducts] = useState(getProducts());
//const [searchValue, setSearchValue] = useState();
const handleAddProductToCart = productID => {
setCartProducts([...cartProducts, productID]);
};
const handleRemoveFromCart = productID => {
const newCartProducts = cartProducts.filter(id => id !== productID);
setCartProducts(newCartProducts);
};
/*const filterItems = ({ description, title }) => {
return title.toLocaleLowerCase().indexOf(searchValue.toLocaleLowerCase())
|| description.toLocaleLowerCase().indexOf(searchValue.toLocaleLowerCase())
}*/
return (
<>
<Header/>
<Search/>
<Sidebar/>
<div>
{products.map(product => {
const { id, title, description, image } = product;
let haveInCart = false;
cartProducts.forEach(productID => {
if (productID === id) {
haveInCart = true;
}
});
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<CardText style={{ border: 'none' }} className="custom-card-text">{description}</CardText>
<FontAwesomeIcon icon={faCartPlus} className="add-icon" onClick={() => handleAddProductToCart(id)} />
</CardBody>
</Card>
);
})}
<h2>Your Cart</h2>
{cartProducts.length > 0
? cartProducts.map(productID => {
const productIndex = products.findIndex(product => {
return product.id === productID;
});
let { id, title, image } = products[productIndex];
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<FontAwesomeIcon icon={faTrash} className="remove-icon" onClick={() => handleRemoveFromCart(id)} />
</CardBody>
</Card>
);
})
: "Yor Cart is Empty :("}
</div>
</>
)
}
export default App;
I want to put product Card and cart Card into it's own component. And when I'm doing it, like this
const Product = ({product}) => {
const { id, title, description, image } = product;
return (
<Card key={id} className="item-card">
<CardImg src={image} alt={title} className="item-img" style={{ height: '260px' }} />
<CardBody style={{ border: 'none' }} className="custom-card-body">
<CardTitle style={{ border: 'none' }} className="custom-card-title">{title}</CardTitle>
<CardText style={{ border: 'none' }} className="custom-card-text">{description}</CardText>
<FontAwesomeIcon icon={faCartPlus} className="add-icon" /*onClick={() => handleAddProductToCart(id)}*/ />
</CardBody>
</Card>
)
}
I'm not getting properties of product in my Card. I want to make my code better organized and save it's functionality. How to access those states from Product and Cart component?
EDIT
Here's the link to codesandbox
https://codesandbox.io/s/late-cookies-r2inh?file=/src/App.jsx&fbclid=IwAR38tcE39tVL51YpG4_6A1HRz-kth1GSIocQWMPrU3QXepc5CHUNn-ZqiG8
EDIT 2 How I can make items in cart be displaying beside Product component, on the left side? Should I create entire Cart component for it?
Your Product.jsx file should look like this:
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faCartPlus } from "#fortawesome/free-solid-svg-icons";
import Card from "react-bootstrap/Card";
import CardBody from "react-bootstrap/Card";
import CardImg from "react-bootstrap/CardImg";
import CardTitle from "react-bootstrap/Card";
import CardText from "react-bootstrap/Card";
const Product = ({ product, handleAddProductToCart }) => {
const { id, title, description, image } = product;
return (
<Card key={id} className="item-card">
<CardImg
src={image}
alt={title}
className="item-img"
style={{ height: "260px" }}
/>
<CardBody style={{ border: "none" }} className="custom-card-body">
<CardTitle style={{ border: "none" }} className="custom-card-title">
{title}
</CardTitle>
<CardText style={{ border: "none" }} className="custom-card-text">
{description}
</CardText>
<FontAwesomeIcon
icon={faCartPlus}
className="add-icon"
onClick={() => handleAddProductToCart(id)}
/>
</CardBody>
</Card>
);
};
export default Product;
And in your App.jsx you can map the products array like this:
{products.map((product) => (
<Product
product={product}
key={product.id}
handleAddProductToCart={handleAddProductToCart}
/>
))}
EDIT:
https://codesandbox.io/s/determined-swartz-5q2fo
I edited the codesandbox, i made the Product component accept both add and remove product callback and the "haveInCart" prop. It will decide which icon and which callback to use base on that prop. I'm not sure about this approch tho

React error Objects are not valid as a React child (found: object with keys {$$typeof, type, compare)

I got a legacy project of Meteor and React and I try to make it work. But I got an error at one point. Can anyone help me to resolve following error?
Uncaught Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, compare}). If you meant to render a collection of children, use an array instead.
in Unknown
in main (created by Basic)
in Basic (created by Context.Consumer)
in Content (created by PageLayout)
in section (created by BasicLayout)
in BasicLayout (created by Context.Consumer)
in Layout (created by PageLayout)
in section (created by BasicLayout)
in BasicLayout (created by Context.Consumer)
in Layout (created by PageLayout)
in section (created by BasicLayout)
in BasicLayout (created by Context.Consumer)
in Layout (created by PageLayout)
in LocaleProvider (created by Context.Consumer)
in LocaleReceiver (created by ConfigProvider)
in ConfigProvider (created by PageLayout)
in PageLayout (created by ForwardRef)
in ForwardRef
in ForwardRef
at throwOnInvalidObjectType (modules.js:64084)
at reconcileChildFibers (modules.js:64984)
at reconcileChildren (modules.js:67433)
at mountIndeterminateComponent (modules.js:68213)
at beginWork (modules.js:69267)
at HTMLUnknownElement.callCallback (modules.js:50859)
at Object.invokeGuardedCallbackDev (modules.js:50908)
at invokeGuardedCallback (modules.js:50963)
at beginWork$1 (modules.js:73874)
at performUnitOfWork (modules.js:72828)
Within the secure.js the PostCategories are mounted like this
ContentRouter.route('/content-creator', {
name: 'Content Creator',
icon: 'solution',
permission: 'main-navigation.view.module.posts',
className: 'posts',
visible: true,
action: () => {
mount(PageLayout, { content: <PostCategories /> });
},
});
The PageLayout looks like this :
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import React, { Component } from 'react';
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
import Konami from 'react-konami-code';
import deDE from 'antd/lib/locale-provider/de_DE';
import moment from 'moment';
import 'moment/locale/de';
import {
ConfigProvider, Layout, Menu, Icon, Steps, Badge, Button, message,
} from 'antd';
import { Workspaces } from '../../../api/workspaces/collection';
import DoneStepper from './components/doneStepper';
import { DASHBOARD_VERSION } from '../../../helpers/Constants';
const {
Header, Content, Sider, Footer,
} = Layout;
moment.locale('de');
class PageLayout extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
logout = () => {
Meteor.logout(() => {
FlowRouter.go('/anmelden');
});
};
renderMenuItems = () => {
const groupName = FlowRouter.current().route.group.name;
const items = FlowRouter._routes.map((route) => {
const isSecure = route && route.group && route.group.parent && route.group.parent && route.group.parent.name === 'secure';
const isVisible = route && route.options && route.options.visible && route.options.visible === true;
const isActive = groupName === route.group.name;
let active = null;
if (isActive) {
active = 'ant-menu-item-selected';
}
return (
isVisible
&& isSecure && (
<Menu.Item key={route.path} style={route.options.style} className={[route.options.className, active]}>
<a href={route.path}>
<Icon type={route.options.icon} />
<span className="nav-text">{route.name}</span>
</a>
</Menu.Item>
)
);
});
return items;
};
easterEgg = () => {
message.success('Development Mode enabled');
};
handleResetWorkspace = () => {
const { user } = this.props;
Meteor.call('workspace.reset', user.profile.workspace, (error) => {
if (error) {
console.log(error);
message.error('error');
} else {
message.success('success');
}
});
};
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true, error: error };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.log(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
console.log('ERROR IS:');
console.log(this.state.error);
return <h1>Something went wrong.</h1>;
}
const { ready, user, workspace, content } = this.props;
if (ready) {
if (workspace && workspace.appName && workspace.appName.name) {
document.title = `App - ${workspace.appName.name}`;
} else {
document.title = 'App';
}
}
return (
<ConfigProvider locale={deDE}>
<Layout className="manager-dashboard">
<Header className="header">
<div className="logo__area">
<a href="/">
<img className="logo" src="/logo.svg" alt="cms" />
</a>
</div>
<DoneStepper />
<Konami action={this.easterEgg}>
<Button type="primary" onClick={() => this.handleResetWorkspace()}>
<Icon type="delete" size="small" />
{'reset workspace'}
</Button>
</Konami>
<div className="member">
<a onClick={this.logout}>
{'Abmelden '}
<Icon type="logout" />
</a>
</div>
</Header>
<Layout>
<Sider width={200} style={{ background: '#fff' }}>
<div className="fixed-sidebar">
<Menu
defaultSelectedKeys={[FlowRouter.current().route.path]}
selectedKeys={[FlowRouter.current().route.path]}
>
{this.renderMenuItems()}
</Menu>
</div>
</Sider>
<Layout className="dashboard__content">
<Content
style={{
background: '#fff',
padding: 20,
minHeight: '100vh',
}}
>
{content}
</Content>
<Footer>{`App - Version ${DASHBOARD_VERSION}`}</Footer>
</Layout>
</Layout>
</Layout>
</ConfigProvider>
);
}
}
export default withTracker(() => {
const user = Meteor.user();
const handleWorkspace = Meteor.subscribe('workspaces.one', {
query: { _id: user.profile.workspace },
fields: { appName: 1 },
});
const ready = handleWorkspace.ready();
let workspace = null;
if (ready) {
workspace = Workspaces.findOne({ _id: user.profile.workspace }, { fields: { appName: 1 } });
}
return {
ready,
user,
workspace,
};
})(PageLayout);
And the PostCategories look like this:
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
import { PostCategories } from '/imports/api/posts/collection';
import React, { Component } from 'react';
import Role from '/imports/helpers/Role';
import CreatePostCategory from '/imports/ui/secure/partials/forms/createPostCategory.js';
import {
Card, Button, message, Row, Col, Icon, Switch, Popover,
} from 'antd';
import Text from '../../components/Text.js';
import Preview from '../../components/preview/index.js';
import CustomSpinner from '../../components/custom-spinner';
const DragIndicator = () => (
<svg viewBox="0 0 14 5" height="15" width="15" xmlns="http://www.w3.org/2000/svg">
<path d="m0 0h14v.83823529h-14z" />
<path d="m0 2h14v.83823529h-14z" />
<path d="m0 4h14v.83823529h-14z" />
</svg>
);
const getItemStyle = (isDragging, draggableStyle) => ({
userSelect: 'none',
...draggableStyle,
});
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
class Categories extends Component {
constructor(props) {
super(props);
this.state = {
categories: props.categories,
createCategory: false,
justReorder: false,
deletePopoverVisible: {},
};
}
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.ready && !prevState.justReorder) {
prevState.categories = nextProps.categories;
prevState.justReorder = false;
} else {
prevState.justReorder = false;
}
return prevState;
}
handleCategoryState = (id, checked) => {
Meteor.call('post.category.state', id, checked, (error) => {
if (error) {
console.log(error);
message.error('error');
} else {
message.success('success');
}
});
};
handleDeletePopoverVisibleChange = (change, id) => {
this.state.deletePopoverVisible[id] = change;
this.setState(this.state);
};
handleDelete = (e, id) => {
e.preventDefault();
Meteor.call('post.category.delete', id, (error) => {
if (error) {
console.log(error);
message.error('error');
} else {
message.success('success');
}
});
};
handleCreateCategory = (e) => {
e.preventDefault();
const form = this.createCategoryForm;
form.validateFieldsAndScroll((err, values) => {
if (err) {
return;
}
values.workspace = this.props.user.profile.workspace;
values.index = this.props.categories.length + 1;
Meteor.call('post.category.insert', values, (error) => {
if (error) {
console.log(error);
message.error('error');
} else {
message.success('success');
form.resetFields();
this.setState({ createCategory: false, categoryId: null });
}
});
});
};
onDragEnd = (data) => {
console.log(data);
const { source, destination, draggableId } = data;
if (!destination) {
return;
}
if (source.droppableId === destination.droppableId) {
this.state.categories = reorder(this.state.categories, data.source.index, data.destination.index);
this.state.categories.forEach((category, idx) => (category.index = idx));
this.state.justReorder = true;
this.setState(this.state, () => {
Meteor.call('post.category.reorder', { categories: this.state.categories }, (error, result) => {
if (error) {
console.log(error);
message.error('error.');
}
});
});
}
};
render() {
const { ready, categories } = this.props;
const { categories: stateCategories, deletePopoverVisible, createCategory } = this.state;
let content = <CustomSpinner />;
if (ready) {
content = (
<Col>
<Row gutter={40}>
<Col xs={24} lg={16} xxl={18}>
{!Array.isArray(categories) ? (
<Row gutter={40}>
<Col
xs={{ span: 24 }}
lg={{ span: 18, offset: 3 }}
xl={{ span: 12, offset: 6 }}
style={{ textAlign: 'center' }}
>
<img src="/emptystates/contentcreator.svg" alt="empty dashboard" />
</Col>
<Col
xs={{ span: 24 }}
lg={{ span: 18, offset: 3 }}
xl={{ span: 16, offset: 4 }}
style={{ textAlign: 'center', marginTop: '40px' }}
>
<h2>Head</h2>
<p>
Text
</p>
<Button
className="button--center"
size="large"
type="primary"
onClick={() => this.setState({ createCategory: true })}
>
Los geht's
<Icon type="right" />
</Button>
</Col>
</Row>
) : (
<div>
<div className="page-title">
<h1>Content Creator</h1>
<p>
Text
</p>
</div>
<Row gutter={40}>
<Col xs={24}>
<div className="shadow-wrapper">
<DragDropContext
onDragEnd={this.onDragEnd}
>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{stateCategories.map((category, index) => (
<Draggable key={category._id} draggableId={category._id} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)}
>
<Card className="card--list-view">
<div>
<div className="card__title">
<span {...provided.dragHandleProps}>
<Icon
component={DragIndicator}
style={{
paddingRight: '20px',
paddingTop: '6px',
}}
/>
</span>
<a href={`/content-creator/kategorie/${category._id}`}>
{category.title}
</a>
</div>
<div className="card__edit">
<span>
<a
href={`/content-creator/neuen-artikel-anlegen?id=${category._id}`}
onClick={() => FlowRouter.go(
'/content-creator/neuen-artikel-anlegen',
{},
{ id: category._id },
)
}
>
<Icon type="folder-add" />
{' Artikel hinzufügen'}
</a>
</span>
<Text
label="Umbenennen der Kategorie"
required
message="Bitte tragen Sie einen Kategorietitel ein."
initialValue={category.title}
render={(
<span>
<Icon
style={{
marginRight: 5,
}}
type="edit"
/>
Umbenennen
</span>
)}
onValid={(result) => {
Meteor.call(
'post.category.edit',
category._id,
{ title: result },
(e) => {
if (e) {
console.log(e);
message.error('Bei dieser Aktion ist ein Fehler aufgetreten');
} else {
message.success('Kategorie Titel erfolgreich erstellt');
}
},
);
}}
/>
<Popover
content={(
<div className="manager-dashboard">
<div
className="page__actions"
style={{ marginBottom: 0, marginTop: 0 }}
>
<Button
type="danger"
onClick={() => this.handleDeletePopoverVisibleChange(false, category._id)
}
>
<Icon type="close" />
{' Abbrechen'}
</Button>
<Button
type="primary"
style={{ marginLeft: '10px' }}
onClick={event => this.handleDelete(event, category._id)}
>
{'Löschen '}
<Icon type="delete" />
</Button>
</div>
</div>
)}
title="Diese Kategorie wirklich löschen?"
trigger="click"
visible={deletePopoverVisible[category._id]}
onVisibleChange={change => this.handleDeletePopoverVisibleChange(change, category._id)
}
>
<Icon type="delete" />
{' Löschen'}
</Popover>
<Switch
style={{ float: 'right' }}
defaultChecked={category.state}
onChange={checked => this.handleCategoryState(category._id, checked)}
checkedChildren="Öffentlich"
unCheckedChildren="Entwurf"
/>
</div>
</div>
</Card>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
{Role.hasPermission('product.category.create') && (
<Card
className="card--list-view add-new-card"
onClick={() => this.setState({ createCategory: true })}
>
<div className="card__title">
<a>+ Neue Kategorie hinzufügen</a>
</div>
</Card>
)}
</div>
</Col>
</Row>
</div>
)}
{createCategory && (
<CreatePostCategory
ref={(form) => {
this.createCategoryForm = form;
}}
visible={createCategory}
onCancel={() => this.setState({ createCategory: false })}
onCreate={this.handleCreateCategory}
/>
)}
</Col>
<Col xs={24} sm={12} lg={8} xxl={6}>
<Preview type="categories" />
</Col>
</Row>
</Col>
);
}
return content;
}
}
export default withTracker(() => {
const user = Meteor.user();
const handleCategories = Meteor.subscribe('posts.categories.all', {
query: { workspace: user.profile.workspace },
sort: { index: 1, title: 1 },
fields: {
title: 1, state: 1, index: 1, workspace: 1,
},
});
const ready = handleCategories.ready();
let categories = null;
if (ready) {
categories = PostCategories.find(
{ workspace: user.profile.workspace },
{
sort: { index: 1, title: 1 },
fields: {
title: 1, state: 1, index: 1, workspace: 1,
},
},
).fetch();
}
return {
user,
ready,
categories,
};
}, Categories);
I am completly clueless what is going wrong, maybe somebody could help me out
React components are functions, and this error message comes about because you are passing in an object rather than a function.
That may be enough for you to find the problem now. It is helpful for us if you can do some narrowing down of the problem, rather than dumping a large amount of code - it becomes too expensive (time consuming) for us to help you if we have to pore through hundreds of lines of code.

how to change state of a react component from another component

I saw dozens of examples but they are not working in my case, I want to update the page variable in "bookitem" component and rerender it. using gives an error ' Expected an assignment or function call and instead saw an expression no-unused-expressions'
import React from 'react'
import { Pagination, Container } from 'semantic-ui-react'
import bookitem from './Book_item'
const PaginationI = () => (
<Container style={{textAlign: "center", padding:'4rem'}}>
<Pagination defaultActivePage={5} totalPages={10} onPageChange={PageChange}/>
</Container>
)
function PageChange(event,data){
console.log(data.activePage);
<bookitem page={data.activePage}/>
};
export default PaginationI
//////////////////////////////////////////////////////////////////////////////////////////////////////
class bookitem extends Component{
constructor(props){
super (props);
this.state={
counter:0,
page:0,
data2:[]
};
}
componentWillMount(){
console.log(this.props.page)
axios.get('/books/'+this.state.page).then(res=>{console.log(res.data);this.setState({data2:res.data});})
console.log('aa')
console.log(this.state.data2)
}
genurl(isbn){
console.log(isbn)
let url='http://covers.openlibrary.org/b/isbn/'+ isbn + '-L.jpg'
return url;
}
render(){return(
<div>
<div>{this.state.page}</div>
<Container>
<div style={{padding:"1em 1em", textAlign: "right"}}>
<Card.Group itemsPerRow={3} stackable={true} doubling={true}>
{this.state.data2.map(card=>(
<Card href="#">
<Image src={this.genurl(card.isbn)} wrapped ui={false} />
<Card.Content>
<Card.Header>{card.title}</Card.Header>
<Card.Meta>
<span className='date'>Author:{card.author}</span>
</Card.Meta>
<Card.Content >
<Rating icon='star' defaultRating={card.avgrating} maxRating={5} />
</Card.Content>
<Card.Description>
{card.avgrating} Avg rating, {card.totalratings} total ratings.
</Card.Description>
</Card.Content>
<Card.Content >
<a>
<Icon name='pencil alternate' />
{card.reviews} Reviews
</a>
</Card.Content>
</Card>
))}
</Card.Group>
</div>
</Container>
</div>
)
}
}
export default bookitem
The problem is that you are not rendering the bookitem component at all. You have to manage the state of your activePage, pass it to the bookitem and actually render this component.
import React, { useState } from "react";
import { Pagination, Container } from "semantic-ui-react";
import BookItem from "./Book_item";
const PaginationI = () => {
const [activePage, setActivePage] = useState(0); // manage the state of activePage
function PageChange(event, data) {
setActivePage(data.activePage); // update the state in event handler
}
return (
<Container style={{ textAlign: "center", padding: "4rem" }}>
<BookItem page={activePage} /> {/* render your component */}
<Pagination
defaultActivePage={5}
totalPages={10}
onPageChange={PageChange} /> {/* pass event handler */}
</Container>
);
};
export default PaginationI;
Also you would have to rename the bookitem component due to collision with HTML tags like this
import React from "react";
class BookItem extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
page: 0,
data2: [],
};
}
componentWillMount() {
console.log(this.props.page);
axios.get("/books/" + this.state.page).then((res) => {
console.log(res.data);
this.setState({ data2: res.data });
});
console.log("aa");
console.log(this.state.data2);
}
genurl(isbn) {
console.log(isbn);
let url = "http://covers.openlibrary.org/b/isbn/" + isbn + "-L.jpg";
return url;
}
render() {
return (
<div>
<div>{this.state.page}</div>
<Container>
<div style={{ padding: "1em 1em", textAlign: "right" }}>
<Card.Group itemsPerRow={3} stackable={true} doubling={true}>
{this.state.data2.map((card) => (
<Card href="#">
<Image src={this.genurl(card.isbn)} wrapped ui={false} />
<Card.Content>
<Card.Header>{card.title}</Card.Header>
<Card.Meta>
<span className="date">Author:{card.author}</span>
</Card.Meta>
<Card.Content>
<Rating
icon="star"
defaultRating={card.avgrating}
maxRating={5}
/>
</Card.Content>
<Card.Description>
{card.avgrating} Avg rating, {card.totalratings} total
ratings.
</Card.Description>
</Card.Content>
<Card.Content>
<a>
<Icon name="pencil alternate" />
{card.reviews} Reviews
</a>
</Card.Content>
</Card>
))}
</Card.Group>
</div>
</Container>
</div>
);
}
}
export default BookItem;
First of all Bookitem must starts with capitalized letter. So instead of <bookitem /> you must have <Bookitem/>.
Now if you want to change state of a react component from another component, you have to pass a function from parent to child which will be called when you want to change the state. For example
const Compoent1 = () => {
const [state, setState] = useState(value)
.....
return <Component2 changeState={setState} />
}

Navigation with UseNavigation()

I am having some trouble understanding the use of UseNavigation. I couldn't find a lot of good examples either. I have this one example where the first button takes us to the Registration Page but I am not sure how exactly. I am trying to edit it in a way that the second button takes me to my login page.
This is my home page:
import Login from './login/Login'
type HomeScreenProps = {};
export const HomeScreen = observer<HomeScreenProps>(() => {
const navigation = useNavigation();
const appStore = useAppStore();
return (
<View style={styles.page}>
<View style={styles.container}>
<Hello />
<Button onPress={() => appStore.hello()}>
<Text>Change State</Text>
</Button>
<Text>The state can also be here: </Text>
<Text>{appStore.helloWorld}</Text>
{/* */}
<Button
onPress={() => navigation.navigate('Registration')}>
<Text>Press to register</Text>
</Button>
<Button
//onPress={() => navigation.navigate('Login')}
>
<Text>Login</Text>
</Button>
</View>
</View>
);
});
Here is the architecture of my login page:
import React, { Component } from 'react';
import { Container, Header, Left, Body, Right, Button, Title, Text, Form, Item, Input, Label} from 'native-base';
import { StackNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { DrawerNavigator } from "react-navigation";
import { createAppContainer } from 'react-navigation';
export class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
}
render() {
return (
<Container>
<Text >Instaride</Text>
<Form>
<Item floatingLabel>
<Label onChangeText={(text) => this.setState({username: text})}>Username</Label>
<Input
value={this.state.username}
onChangeText={username => this.setState({ username })}
placeholder={'Username'}
/>
</Item>
<Item floatingLabel last>
<Label >Password</Label>
<Input
value={this.state.password}
onChangeText={password => this.setState({ password })}
placeholder={'Password'}
secureTextEntry={true}
/>
</Item>
</Form>
<Left>
<Button onPress={() => this.props.navigation.navigate("Details")}>
<Text>Login</Text>
</Button>
<Text >Forgot Password?</Text>
</Left>
<Right>
<Button hasText transparent>
<Text>Sign Up Here</Text>
</Button>
</Right>
</Container>
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<Text>Details Screen</Text>
);
}
}
class RegisterationScreen extends React.Component {
render() {
return (
<Text>sign up time</Text>
);
}
}
const LoginRouter = createStackNavigator(
{
Home: { screen: Login },
Details: { screen: DetailsScreen },
}
)
export default createAppContainer(LoginRouter);
but it gives an error. How can I change it? Why is the method working on the registration page but not my login page?
This is from the App.tsx file:
onst App: React.FC<AppProps> = () => {
// Disable mapbox telemetry due to privacy policy
useEffect(() => {
MapboxGL.setTelemetryEnabled(false);
});
return (
<NavigationNativeContainer>
<NavigationStack.Navigator initialRouteName="Home">
<NavigationStack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<NavigationStack.Screen
name="Registration"
component={RegistrationScreen}
options={{ headerShown: false }}
/>
{/* <NavigationStack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/> */}
<NavigationStack.Screen name="Details" component={DetailsScreen} />
</NavigationStack.Navigator>
</NavigationNativeContainer>
);
};
I get an error that "Login" is not found when I uncomment that section.

Categories