I'm just starting to learn Meteor with React using es6, and I'm having trouble understanding this.props. Where does it come from? I don't have any code where I define it for the class myself. Thank you in advance.
This is a portion of my code in simple-todos/imports/ui/App.jsx:
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import ReactDOM from 'react-dom';
import { Tasks } from '../api/tasks.js';
import Task from './Task.jsx';
class App extends Component {
renderTasks() {
return this.props.tasks.map((task) => (
<Task key={task._id} task={task} />
));
}
}
This props contains the properties that are passed to the component upon creation. E.g:
<SomeComponent someProperty={'foo'} />
Now inside SomeComponent you can now access someProperty as this.props.someProperty
Read more about using props here.
It allows you to make more "arbitrary" components. For example, say you have a list that fetches from a server.
export default class List extends Component {
static propTypes = {
data: PropTypes.array.isRequired
}
render() {
return (
//you can now be sure that the proptypes are what you wanted them to be.
)
}
}
That way, you can just pass the array of data to this component
<List data={users} />
Related
I am migrating from my Create React App (client-side-rendering) to Next JS (server-side rendering) due to SEO reasons. Migrating was going well until using React-Redux-Firebase / Firestore. This is the page I am trying to load:
Discover.js
import React, { Component } from 'react'
import { firestoreConnect, isEmpty } from 'react-redux-firebase';
import { compose } from 'redux'
import { connect } from "react-redux";
import { blogpostsQuery } from '../blogposts/blogpostsQuery';
import DiscoverList from "./DiscoverList";
const mapState = (state, ownProps) => {
let blogposts = {};
blogposts =
!isEmpty(state.firestore.ordered.blogposts) &&
state.firestore.ordered.blogposts;
return {
blogposts,
};
};
class DiscoverPage extends Component {
render() {
const {blogposts} = this.props
return (
<div className="container">
<div className="hero">
<h1>Discover stories</h1>
<p className="lead">Blogpost published:</p>
</div>
<DiscoverList blogposts={blogposts} />
</div>
)
}
}
export default compose(
firestoreConnect(() => blogpostsQuery()),
connect(mapState, null)
)(DiscoverPage)
The error I received is this:
ReferenceError: XMLHttpRequest is not defined
at Rn.ca (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:36966)
at Ie (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:18723)
at Se (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:18385)
at Kn.a.Ia (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:39600)
at jt (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:15360)
error Command failed with exit code 1.
I wasn't the only one with this problem and I have found the solution on GitHub by prescottprue:
https://github.com/prescottprue/react-redux-firebase/issues/72
Including documentation: http://react-redux-firebase.com/docs/recipes/ssr.html
// needed to fix "Error: The XMLHttpRequest compatibility library was not found."
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
The problem is (sorry i am new developer) I have no idea where to add this line of code? Adding it to _app.js doesnt work.. i've added https://www.npmjs.com/package/xmlhttprequest but still no luck...
-app.js
import App from "next/app";
import { Provider } from "react-redux";
import React, { Fragment } from "react";
import withRedux from "next-redux-wrapper";
import "../src/styles.css";
import configureStore from "../src/app/store/configureStore";
import Header from "../src/app/layout/Header";
import NavBar from "../src/app/layout/nav/Navbar/NavBar";
import Footer from "../src/app/layout/Footer";
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
//Anything returned here can be accessed by the client
return { pageProps: pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<Fragment>
<Header />
<NavBar />
<Provider store={store}>
<Component {...pageProps} />
</Provider>
<Footer />
</Fragment>
);
}
}
export default withRedux(configureStore)(MyApp);
Could somebody help me?
Many thanks
Frido
I am currently learning how to user lit-element v2.0.0-rc.2 I have two components app.js and list-items.js. In app.js I am collecting data from local storage and storing it in this.todoList, Im then calling this.todoList in my list-items.js but the problem I am running into is that it is not passing the data as an array but as an object, I am trying to output that data in list-items all Im getting when I do a console.log of this.todoList is [object] in my tags it is rendering out with dots for the tag but no data. I was wondering If i could get some help in understanding why this is happening . here is my code
app.js
'''
import {LitElement, html} from 'lit-element';
import './add-item';
import './list-items';
class TodoApp extends LitElement{
static get properties(){
return{
todoList: Array
}
}
constructor(){
super();
let list = JSON.parse(localStorage.getItem('todo-list'));
this.todoList = list === null ? [] : list;
}
render(){
return html `
<h1>Hello todo App</h1>
<add-item></add-item>
<list-items todoList=${this.todoList}></list-items>
`;
}
}
customElements.define('todo-app', TodoApp)
list-items.js
import { LitElement, html } from 'lit-element';
import {repeat} from 'lit-html/directives/repeat.js';
import './todo-item';
class ListItems extends LitElement {
static get properties(){
return{
todoList: Array
}
}
constructor(){
super();
this.todoList = [];
}
render(){
console.log(this.todoList)
return html `
<ul>${repeat(this.todoList, (todo) => html`<todo-item
todoItem=${todo.item}></todo-item`)}</ul>
`;
}
}
customElements.define('list-items', ListItems);
'''
the result I am looking for is the for the data stored in local storage to be listed on my rendered page.
Attributes are always text. Because todoList an array, it's a property, not attribute. Try binding as a property: .todoList="${this.todoList}". See https://lit-element.polymer-project.org/guide/templates#bind-properties-to-child-elements (Updated link for Lit, https://lit.dev/docs/templates/expressions/#property-expressions)
I am working on this project where we're using this template from MS and it's all working nice but for this particular task I am in a need for 'default' dispatch method from redux so I can focus on some form inputs and I cannot figure out how to get it.
import { ApplicationState } from '../../../store/index';
import { connect } from 'react-redux';
import * as GlobalState from '../../../store/Global';
import { Field } from 'redux-form';
import SelectHour from '../Selects/SelectHour';
import Select from '../Selects/Select';
import MultiSelectComponent from '../Selects/MultiSelectComponent';
import Days from '../Days';
import { getFormInitialValues } from 'redux-form';
import { Field, focus, blur } from 'redux-form';
import SelectHour from './SelectHour';
class WorkingDays extends React.Component<Props, State> {
...
}
export default connect(
(state: ApplicationState) => state.global,
GlobalState.actionCreators
)(WorkingDays) as typeof WorkingDays;
How can I get access to dispatch so I can use it something like this?
this.props.dispatch.focus(something, something)
dispatch is a function, so you can't make this.props.dispatch.focus(something, something) work.
But can get this.props.focus(something, something) by this way:
export default connect(
(state: ApplicationState) => state.global,
(dispath) => ({
focus: (value1, value2) => {
const action = yourAction(value1, value2)
dispath(action)
}
})
)(WorkingDays) as typeof WorkingDays;
I have never worked with MS react-redux template so I do not know what your GlobalState is look like!
I am using React and splitting CSS with each Component.
and I want to extract CSS from these files.
// ComponentA.js
import "./ComponentA.css"
export default class ComponentA extends React.Component {
...
}
// ComponentB.js
import "./ComponentB.css"
export default class ComponentB extends React.Component {
...
}
// index.js
import ComponentA from "./ComponentA"
import ComponentB from "./ComponentB"
class App extends React.Component {
render() {
return (
<div>
<ComponentA />
<ComponentB />
</div>
)
}
}
in this case, how can i extract and bundle ComponentA.css and ComponentB.css
without transpile whole JS sources?
You need to use extract-text-plugin to do this. It will bundle your css to one file.
read more about this plugin
I'm using react and I found this awesome library that helps you define css classes for components called classNames.
I'm also using the webpack css-loader in order to import css into my component and when trying to use classNames with import css I get a syntax error.
Here is my example:
import React from 'react';
import styles from './style.css';
import classNames from 'classnames';
export default class Menu extends React.Component {
render() {
let style = classNames({
styles.someClass: true
});
}
}
How can I use both?
You can use the computed properties syntax of ES6/2015, for example:
import React from 'react';
import styles from './style.css';
import classNames from 'classnames';
export default class Menu extends React.Component {
render() {
const style = classNames({
// This is a computed property, i.e. surrounded by []
[styles.someClass]: true
});
}
}
But that is just for a single class, in these simple cases you could just do something like:
const style = this.state.active ? styles.someClass : '';
The classNames library is especially useful when combining multiple classes, like so:
import React from 'react';
import styles from './style.css';
import classNames from 'classnames';
export default class Menu extends React.Component {
render() {
const style = classNames(
// add as many classes or objects as we would like here
styles.foo,
styles.bar,
{ [styles.someClass]: this.props.active }
);
}
}