asynchron firestore query with mapStateToProps - reactjs

I would like to use some data I received from firestore to build a quiz. Unfortunately I can console.log the array, but if I use .length it is undefined.
Is this problem caused by some lifecycle or asnynchronous issue?
Thanks in advance!
import React, { Component } from 'react';
import { connect } from 'react-redux';
class LernenContainer extends Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div className="lernenContainer">
LernenContainer
{
console.log(this.props.firestoreData),
// prints array correctly
console.log(this.props.firestoreData.length)
// is undefined
}
</div>
);
}
}
const mapStateToProps = state => {
return {
firestoreData: state.firestoreData
};
};
const mapDispatchToProps = dispatch => {
return {
// todo Achievements
};
};
export default connect(mapStateToProps, mapDispatchToProps) (LernenContainer);
console.log(this.props.firestoreData):

Try below code
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types'
class LernenContainer extends Component {
constructor(props) {
super(props);
}
static propTypes = {
firestoreData: PropTypes.object.isRequired
}
render() {
const { firestoreData } = this.props
console.log(firestoreData);
console.log(firestoreData.length);
return (
<div className="lernenContainer">
</div>
);
}
}
const mapStateToProps = (state) => ({
firestoreData: state.firestoreData
})
const mapDispatchToProps = (dispatch) => ({
})
export default connect(mapStateToProps,mapDispatchToProps)(LernenContainer);

Related

How to use mapStateToProps in class component in React?

Login.js in functional component
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { login } from '../actions/auth';
const Login = ({ login, isAuthenticated }) => {
return (
<div>
// some code here
</div>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { login })(Login);
How can I use above mapStateToProps function in class component as I used above in functional component?
Login.js in class component
import React, {Component} from "react";
class Login extends Component{
constructor(props) {
super(props);
this.state = {
search:'',
}
}
render() {
return(
<div>
//some code here
</div>
)
}
}
export default Login;
In class components mapStateToProps works the same as functional components, I feel there are only differences in some syntax or calling approaches.
It does not matter if a mapStateToProps function is written using the function keyword (function mapState(state) { } ) or as an arrow function
(const mapState = (state) => { } ) - it will work the same either way.
Class component with mapStateToProps
import React, {Component} from "react";
import { connect } from 'react-redux';
import { login } from '../actions/auth';
class Login extends Component{
constructor(props) {
super(props);
this.state = {
search:'',
}
}
render() {
const { isAuthenticated } = this.props;
return(
<div>
//some code here
</div>
)
}
}
function mapStateToProps(state) {
const { isAuthenticated } = state.auth.isAuthenticated
return { isAuthenticated }
}
export default connect(mapStateToProps)(Login)
As you can see there is only 1 major difference is: In Class component we are reading the value isAuthenticated from this.props whereas in the Functional component we are getting the value as arguments.
For information read more about mapStateToProps. https://react-redux.js.org/using-react-redux/connect-mapstate

my mapdispatch to props is automatically calling

Post component:
import React from 'react';
import './post.styles.scss';
import { connect } from 'react-redux';
import { requestContents } from '../../redux/post/post.actions';
class Post extends React.Component {
componentWillMount(){
}
render(){
return (
<div>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onRequestContents : dispatch(requestContents())
}
}
const mapStateToProps = (state) => {
return {
posts: state.post.posts,
isPending: state.post.isPending
}
}
User component:
export default connect(mapStateToProps, mapDispatchToProps)(Post)
import React from 'react';
import './user.styles.scss';
import { connect } from 'react-redux';
import { requestUsers } from '../../redux/user/user.actions';
class User extends React.Component {
componentWillMount(){
this.props.onRequestUsers();
}
render(){
return (
<div>
</div>
}
}
const mapDispatchToProps = (dispatch) => {
return {
onRequestUsers: () => dispatch(requestUsers())
}
}
const mapStateToProps = (state) => {
return {
users: state.user.users,
isPending: state.user.isPending
}
}
export default connect(mapStateToProps, mapDispatchToProps)(User)
Here I am using redux with React.
In user component i am calling onRequestUsers inside componentWillMount()
but in post component i am not calling onRequestContents inside componentWillMount()
But still how it is calling and display in my redux-logger
I am calling mapDispatchToProps only inside user component
Please have a look
You're calling requestContents in your mDTP call:
const mapDispatchToProps = (dispatch) => {
return {
onRequestContents: dispatch(requestContents())
}
}
That's what those two parens do:
requestContents()
Omit them:
onRequestContents: dispatch(requestContents)
That said: there's something odd with your function. Normally you'd mDTP with a function, e.g.,
onRequestContents: () => dispatch(requestContents())
(Used when you need to pass parameters, like an event.)

How to update state from other component?

I am using react native and react navigation for routing.
How to update state from another component/page?
HomeScreen
export class HomeScreen extends Component {
constructor(){
this.state = {
test: ''
}
}
updateState = ()=>{
this.setState({test:'new value'});
}
}
SideMenuScreen
import { HomeScreen } from "./home";
export class SideMenuScreen extends Component {
updateHomeState = ()=>{
let oHome = new HomeScreen();
oHome.updateState();
}
}
My App.js and routing and sidemenu config as below :
import { createAppContainer, createDrawerNavigator } from "react-navigation";
import { SideMenuScreen } from "./screens/Sidemenu";
import { HomeScreen } from "./screens/Home";
export default class App extends Component {
render() {
return(
<AppContainer></AppContainer>
);
}
}
const AppNavigator = createDrawerNavigator(
{Home: HomeScreen,
other: otherpage},
{
contentComponent: SideMenuScreen
}
);
const AppContainer = createAppContainer(AppNavigator);
updateState executing but not updating state.
If you have to update from the child component
You will have to pass down the Handlers from the component which holds the state to update the values, child component can make use of these handlers to update the state
If you have to update from some other location
You will have to do a level up the State and follow the same has above.
LevelUpComponent
export class App extends Component {
constructor(){
this.state = {
test: ''
}
}
updateState = (values)=>{
this.setState(values);
}
render(){
return <div>
<HomeScreen></HomeScreen>
<SideMenuScreen updateState={this.updateState}></SideMenuScreen>
</div>
}
}
Since you're not haveing Parent-Child relationship between your components ... thi s could be accomplished through Redux Action
HomeScreen;
export class HomeScreen extends Component {
constructor() {
this.state = {
test: ""
};
}
componentWillReceiveProps(nextProps) {
const { test: nextTest } = nextProps;
const { test } = this.props;
if (nextTest !== test) {
this.setState({ test: nextTest });
}
}
}
const mapStateToProps = ({ yourReducerName: test }) => ({ test });
export connect(mapStateToProps)(HomeScreen);
import { HomeScreen } from "./home";
import { connect } from "tls";
class SideMenuScreen extends Component {
updateHomeState = () => {
const { updateHomeStateAction } = this.props;
updateHomeStateAction({ test: 'New Value' });
};
}
export default connect(null, { updateHomeStateAction })(SideMenuScreen);
when you navigate to next screen pass this function in params,
this.props.navigate("SideMenuScreen",{update:this.updateState});
And in your side menu screen,
call it using props,
this.props.navigation.state.params.update();//you can pass params also if needed
You can do this by using ref.
HomeScreen
export class HomeScreen extends Component {
constructor(){
this.state = {
test: ''
}
}
updateState = ()=>{
this.setState({test:'new value'});
}
}
SideMenuScreen
import { HomeScreen } from "./home";
export class SideMenuScreen extends Component {
updateHomeState = ()=>{
this.homeScreen.updateState();
}
render(){
return(
<HomeScreen ref={(ele) => this.homeScreen = ele}/>
);
}
}

List not rendering to parent component

I'm building a Todo app using react+redux. When I add new todo in my list, state of store and state of TodoList component are updated successfully but My todoList code not working properly. React component is not rendering list.
Structure of state is below.
State = [
{
id,
text,
completed
},...
]
My code is below.
Todo.js
import React, { Component } from 'react';
import Form from './Form';
import TodoList from './TodoList';
import Filter from './Filter';
class ToDo extends Component {
render() {
return (
<div>
<h2>Todo App</h2>
<Form />
<TodoList />
<Filter />
</div>
);
}
}
export default ToDo;
TodoList.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { toggleToDo } from '../actions';
class TodoList extends Component {
constructor (props){
super(props);
this.state = {
list: []
};
}
render() {
console.log(this);
const todolist = this.state.list;
return (
<ul>
{
todolist.map(function(listValue) {
return <li>{listValue.text}</li>;
})
}
</ul>
);
}
}
const mapStateToProps = (state) => {
console.log('TodoList state',state);
return {
todos: state
}
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({toggleToDo},dispatch);
}
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
You are mapping your state to props with mapStateToProps so you should get this state value from your props.
const { todos } = this.props; and iterate on todos instead of todolist.

mapStateToProps is undefined though connect imported syntax error

I have this error and can't really understand what could go wrong when {connect} imported and const mapStateToProps declared:
./src/Movies.js Syntax error: C:/projects/library/src/Movies.js:
Unexpected token (6:8)
6 | const mapStateToProps = (state) => ({
import React, { Component } from "react";
import { connect } from "react-redux";
import MovieItem from "./MovieItem";
class Movies extends Component {
const mapStateToProps = (state) => ({
movies: state.movies;
});
render() {
let movieItems = this.props.movies.map(movie => {
return <MovieItem movie={movie} />;
});
return <div className="Movies">{movieItems}</div>;
}
}
export default connect(mapStateToProps, null)(Movies);
You need to define mapStateToProps function outside of your React component
import React, { Component } from "react";
import { connect } from "react-redux";
import MovieItem from "./MovieItem";
class Movies extends Component {
render() {
let movieItems = this.props.movies.map(movie => {
return <MovieItem movie={movie} />;
});
return <div className="Movies">{movieItems}</div>;
}
}
const mapStateToProps = (state) => ({
movies: state.movies;
});
export default connect(mapStateToProps, null)(Movies);
A class member cannot be declared as a const, var or let. Also since you need to use it outside of the React component only, you should define it separately

Resources