I'm totally stuck with passing data from container to component When using Meteor and React. I thought I had just copied the code from Meteor React tutorial and customized a little bit, but it doesn't work somehow. What I wanna do is getting data from a database(QuestionModel) and simply output in a view. According to an error message in browser, this.props.questions in renderQuestions() is undefined... But I explicitly passed the data to the component.
Could anyone help me out? Thank you.
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Questions as QuestionsModel } from '../../api/questions.js';
import { QuestionList } from '../QuestionList.jsx';
class Questions extends Component{
renderQuestions(){
let filteredQuestions = this.props.questions;
//This doesn't work at all...
console.log(this.props.questions);
return filteredQuestions.map((question) => (
<QuestionList key={question._id} question={question} />
));
}
render(){
return (
<div className="questionlist">
<ul>{this.renderQuestions()}</ul>
</div>
);
}
}
Questions.propTypes = {
questions: PropTypes.array.isRequired,
};
export default QuestionsContainer = createContainer(() => {
//This console.log outputs the data correctly.
console.log(QuestionsModel.find({}).fetch());
const questions = QuestionsModel.find({}).fetch();
return {
questions,
};
}, Questions);
What is the code of your QuestionList component?
I just replaced it with <li key={question._id}>{question.question}</li> and it works perfectly for me.
Something else: do you import /imports/api/questions.js'; server-side?
Here is my code:
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Questions as QuestionsModel } from '../api/questions.js';
// import { QuestionList } from '../QuestionList.jsx';
class Questions extends Component{
renderQuestions(){
let filteredQuestions = this.props.questions;
//This doesn't work at all...
console.log(this.props.questions);
return filteredQuestions.map((question) => (
<li key={question._id}>{question.question}</li>
));
}
render(){
return (
<div className="questionlist">
<ul>{this.renderQuestions()}</ul>
</div>
);
}
}
Questions.propTypes = {
questions: PropTypes.array.isRequired,
};
export default QuestionsContainer = createContainer(() => {
//This console.log outputs the data correctly.
console.log(QuestionsModel.find().fetch());
const questions = QuestionsModel.find({}).fetch();
return {
questions,
};
}, Questions);
Related
I have a React/TypeScript Component that I'm trying to import mock data into and then iterate over it to display a specific attribute in a span element.
The issues I'm running into are that I can't seem to pass the mock data into my component to iterate over it and at the same time I'm also getting weird type errors that seem to suggest that I'm either using the type definitions of my data or the data itself for my props but never both.
I created a CodeSandbox to highlight these issues and I included my main component where I'm seeing the errors below:
Current Component
import React from 'react';
import contacts from '../../mock-data/contacts-mock-data';
import { Contacts, ContactGroup } from '../../services/contacts-client';
type Props = {
contacts: Contacts[];
contactGroups: ContactGroup[];
};
export const ContactGroupsSection = (props: Props) => {
const { contacts, contactGroups } = props
let groups = () => {
for (let i = 0; i < contacts.contactGroups.length; i++) {
return <span>{contacts.contactGroups.contactGroup}</span>;
}
};
return (
<div>{groups}</div>
);
};
I tweaked your codesandbox to pass the data into your component as you suggested.
App.js
import React from "react";
import "./styles.css";
import { ContactGroupsSection } from "./contact-groups";
import contacts from "./contacts-mock-data";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<ContactGroupsSection contacts={contacts} />
</div>
);
}
contact-groups.tsx
import React from "react";
import { Contacts } from "./contact-types";
type Props = {
contacts: Contacts;
};
export const ContactGroupsSection = ({ contacts }) => {
const groups = contacts.contactGroups.map(contactGroup => (
<span>{contactGroup.contactGroup}</span>
));
return <div>{groups}</div>;
};
Hope that helps!
I just started using typescript so pardon me if I am staring right at the solution. I have a component as follows
import './weatherInfo.css';
import * as React from 'react';
import { connect } from 'react-redux';
import IWeatherInfo from '../../models/WeatherInfo';
import {IApplicationState} from '../../reducers';
import WeatherInfo from './weatherInfoItem';
interface IWeatherInfoList{
weatherInfoList:IWeatherInfo[]
}
class WeatherInfoList extends React.Component<IWeatherInfoList> {
componentWillReceiveProps(){
console.log("Component will recieve props"); <------ 1
}
render() {
console.log(this.props.weatherInfoList);
return (
<div className="weatherInfoContainer">
{this.props.weatherInfoList.map((weatherInfoItem, index)=>{
debugger
return (<WeatherInfo key={index} {...weatherInfoItem}/>);
})}
</div>
);
}
}
function mapStateToProps(state: IApplicationState):IWeatherInfoList {
<------- 2
return {
weatherInfoList: state.weatherInfo.citiesWeatherData
}
}
const mapDispatchToProps = {
};
export default connect(mapStateToProps, mapDispatchToProps)(WeatherInfoList);
state.weatherInfo.citiesWeatherData is of type IWeatherInfo[]
Now whenever I update the store state all is looking good, the store get updated. But the component doesn't get new props (hence it isn't rerendered). So I put a break point at 2 and 1. It stops at 2 but not at 1. I tried changing the type of weatherInfoList to a string array and then it is working. What am I missing here?
I'm new to react and trying to create a ecommerce website. For the navigation and category items, I have used a endpoint url.
http://149.129.128.3:3737/search/resources/store/1/categoryview/#top?depthAndLimit=-1,-1,-1,-1
and the screenshot of response is given below
The problem which I'm facing is that when I click on the categories like Apparel, Electronics, upto the first level of category, I'm able to render it.
But under that subsection, there is another category, which I'm not able to render(E.g under Girls there is shoes, pants etc) and the code is given below
topNavigation.js
import React, { Component } from 'react';
import axios from 'axios';
import SubMenu from './subMenu';
class Navigation extends Component {
state = {
mainCategory: []
}
componentDidMount() {
axios.get('http://localhost:3030/topCategory')
.then(res => {
console.log(res.data.express);
this.setState({
mainCategory: res.data.express.catalogGroupView
})
})
}
render() {
const { mainCategory } = this.state;
return mainCategory.map(navList => {
return (
<ul className="header">
<li key={navList.uniqueID}>
<a className="dropbtn ">
{navList.name}
<ul className="dropdown-content">
<SubMenu below={navList.catalogGroupView}/>
</ul>
</a>
</li>
</ul>
)
})
}
}
export default Navigation;
subMenu.js
import React, { Component } from 'react';
import SubListMenu from './subListMenu';
class SubMenu extends Component {
render() {
const {below} = this.props;
return below.map(sub => {
return (
<div>
<li key={sub.uniqueID}> <a>{sub.name}</a></li>
<SubListMenu subBelow={this.props}/>
</div>
)
})
}
}
export default SubMenu;
subListMenu.js
import React, { Component } from 'react';
class SubListMenu extends Component {
render() {
const {subBelow} = this.props;
return subBelow.map(sub => {
return (
<li key={sub.uniqueID}> <a>{sub.name}</a></li>
)
})
}
}
export default SubListMenu;
Can someone please help me on this. I'm not able to figure it out. I don't know where my code is getting wrong. Or if somebody could atleast give an insight how to proceed further.
Try to change this line:
<SubListMenu subBelow={this.props}/>
to this:
<SubListMenu {...this.props}/>
or to this
<SubListMenu subBelow={this.props.below}/>
You are passing the whole props object to subBelow, so you are trying to map through an object, but Object.prototype.map is not a function.
I need to be able to get the current navigation state from my registered screen components. I expected to find a routes object inside the navigation.state object but alas its not there. I have managed to get this working by setting up my root component in the following way, however this seems convoluted and i cant help but think there must be a cleaner way to achieve this.
App.js
import React, {Component} from 'react'
import {Tabs} from './components/Routes'
import {NavigationActions} from 'react-navigation'
export default class App extends React.Component {
state = {
navState: null
}
componentDidMount(){
const initState = Tabs.router.getStateForAction(NavigationActions.init())
this.getState(null, initState);
}
getState = (prevState, newState) => {
let activeIndex = newState.index
let navState = newState.routes[activeIndex]
this.setState({navState})
}
render() {
return (
<Tabs
onNavigationStateChange={this.getState}
screenProps={{navState: this.state.navState}}/>
)
}
}
<NavigationName
onNavigationStateChange={(prevState, newState) => {
this._getCurrentRouteName(newState)
}}
/>
_getCurrentRouteName(navState) {
if (navState.hasOwnProperty('index')) {
this._getCurrentRouteName(navState.routes[navState.index])
} else {
console.log("Current Route Name:", navState.routeName)
this.setState({navState: setCurrentRouteName(navState.routeName)})
}
}
I have done this before and I am providing a key, but for some reason I am still getting the error. I am a bit new to react so it could be a silly mistake somewhere.
Edit: Error is the each child in an array should have a unique key
Here is the code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import _ from 'lodash';
class BooksList extends Component {
renderList() {
return _.map(this.props.books, book => {
return (
<div key={book.id}>
<h2>{book.title}</h2>
<h3>{book.description}</h3>
<h4>{book.price}</h4>
</div>
);
});
}
render() {
return (
<div>
{this.renderList()}
</div>
);
}
}
function mapStateToProps(state) {
return {
books: state.books
}
}
export default connect(mapStateToProps)(BooksList);
Edit:
I tried binding this.renderList, in the constructor, but still have the same issue:
constructor(props) {
super(props);
this.renderList = this.renderList.bind(this);
}
Your issue is you are not loading the books before the map happens initially.. so you have invalid data initially.
Initially this.props.books is this
then you load the books and it turns to this.
The fix for this is to only render when you have a valid object. Use the lodash isEmpty check for an object... use a forEach so you dont return empty in an array (less items to hold in array). and then just return that array at the end :)
renderList() {
const elems = [];
_.forEach(this.props.books, book => {
if (_.isEmpty(book)) return;
elems.push(
<div key={book.id}>
<h2>{book.title}</h2>
<h3>{book.description}</h3>
<h4>{book.price}</h4>
</div>
);
});
return elems;
}