Pass array to component - reactjs

I'm getting a problem trying to send an array that I get from my DB, from a component to another.
I mean, I'm obtaining JSON data and then that data has to be passed to another component.
I was thinking about using the map method.
I checked my console and I noticed that I get the correct data from the DB but when I'm trying to send it by the state, in the class that I want to get the info is null
Class which gets the objects:
import React from 'react'
import { withRouter } from 'react-router-dom'
import MovieList from './MovieList'
import MoviesService from '../services/MoviesService'
class MovieListGet extends React.Component {
constructor (props) {
super(props)
this.state = {
movies: []
}
}
async componentDidMount () {
await this._getMovies()
}
async _getMovies () {
const response = await MoviesService.getMovies()
this.setState({ movies: response.data })
console.log(this.state.movies)
}
async _deleteMovie (id) {
}
_navigateToCreateMovies () {
// Adrress
}
render () {
return (
<div>
<MovieList
movies = {this.state.movies}
onCreateMovie={this._navigateToCreateMovies.bind(this)}
onDelete={this._deleteMovie.bind(this)}
/>
</div>
)
}
}
export default withRouter(MovieListGet)
Class that has to get the array
/* eslint-disable react/prop-types */
import React from 'react'
import {...} from '#material-ui/core'
import { ... } from '#material-ui/icons'
class MovieList extends React.Component {
constructor (props) {
super(props)
const { movies } = props
this.state = {
_movies: []
}
}
componentDidMount () {
console.log(this.props.movie)
this.setState({ _movies: this.props.movies })
}
_renderMovies () {
if (!this.state._movies || this.state._movies.length < 1) {
return (
// Something
)
} else {
return this.state._movies.map(m => (
// something
)
)
}
}
render () {
return (
// Something
)
}
}
export default (MovieList)

MoviesListGet should pass the prop like this:
<MovieList
movies={this.state.movies}
onCreateMovie={this._navigateToCreateMovies.bind(this)}
onDelete={this._deleteMovie.bind(this)}
/>
Then in MoviesList component you can use it like this in you renderMovies method:
class MovieList extends React.Component {
renderMovies () {
if (!this.props.movies || this.props.movies.length < 1) {
return (
// Something
)
} else {
return this.props.movies.map(m => (
// something
)
)
}
}
render () {
return (
// Something
)
}
}
export default MovieList;

Related

How do I export or call method from component in another component in react?

I am new in react. Maybe someone can help me. I have 2 components. getData() in Weather Component should call the method getPoint() from the component PointsOfInterest. How can I do that?
Component 1:
import React from 'react';
import { getPoint, PointsOfInterest } from './PointsOfInterest'
class Weather extends React.Component {
getWeather = async (city) => {
...
}
}
getData = async (city) => {
await this.getWeather(city)
getPoint(this.state.latitude, this.state.longitude);
}
render()
{
return ... }
Component 2:
export class PointsOfInterest extends React.Component {
state = {nameOfPoints: ''}
fetchToken = async () => {
...
}
getPoint = async (latitude, longitude) => {
const auth = await this.fetchToken()
...
}
render(){
return(...)
}
}
export default PointsOfInterest;
While importing PointsOfInterest in weather component, you can have an additional prop ref in PointsOfInterst (as shown below) . By ref you can access the methods of PointsOfInterst in weather component. I have done the code changes below for Weather component
You can do like
import React from 'react';
import { getPoint, PointsOfInterest } from './PointsOfInterest'
class Weather extends React.Component {
constuctor(props){
// Changes made here
this.pointOfIntrst = React.createRef();
}
getWeather = async (city) => {
...
}
}
getData = async (city) => {
await this.getWeather(city)
if(this.pointOfIntrst.current) {
await this.pointOfIntrst.current.getPoint(this.state.latitude,
this.state.longitude);
}
}
render()
{
<PointsOfInterest ref = {this.pointOfIntrst} .../>
return ... }

asynchron firestore query with mapStateToProps

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);

How to continue mounting if condition is met?

I am using react and I have componentWillMount which looks like this
componentWillMount() {
axios.get('/user').then(response => {
console.log(response.data.user)
if (response.data.user) {
} else {
this.props.history.replace('/signup');
}
});
}
Notice this line here in the code.
if (response.data.user) {
}
Now, How can I make my container render if the condition is met?
You just need to set the user variable in the component state once you received it in then method, and later you can use it in your render method:
import React from 'react'
class App extends React.Component {
constructor (props) {
super(props)
this.state = { user: null }
}
componentWillMount() {
axios.get('/user').then(response => {
if (response.data.user) {
this.setState({ user: reaponse.data.user )}
} else {
this.props.history.replace('/signup')
}
})
}
render() {
// Do something with the user
if (this.state.user) {
return <div>{this.state.user.name}</div>
}
return <div />
}
}
Hy, render conditionally based on state.
import React from "react";
class ExampleComponent extends React.PureComponent {
state={ user: null }
static getDerivedStateFromProps(nextProps, prevState){
if(!prevState.user && state.user){
this.props.history.replace('/signup');
}
else return null;
}
componentWillMount() {
axios.get('/user').then(response => {
console.log(response.data.user)
if (response.data.user) {
this.setState({ user: response.data.user )}
}
});
}
render() {
const { user } = this.state;
return user ? <div>have user, can return null</div> : <div>loading user</div>
}
}
export default ExampleComponent;

Lazy Loading Routes in React With Typescript AsyncComponent

I'm trying to lazy load routes in React by implementing the AsyncCompoment class as documented here Code Splitting in Create React App. Below is the es6 asyncComponent function from the tutorial:
import React, { Component } from "react";
export default function asyncComponent(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : null;
}
}
return AsyncComponent;
}
I've written this function in typescript and can confirm that components are indeed being loaded lazily. The issue I face is that they are not being rendered. I was able to determine that the component object is always undefined in the componentDidMount hook:
//AsyncComponent.tsx
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
The object being returned from the importComponent function has the following properties:
{
MyComponent: class MyComponent: f,
__esModule: true
}
I modified the componentDidMount method to take the first property of this object, which is the MyComponent class. After this change my project is now lazy loading the components and rendering them properly.
async componentDidMount() {
const component = await importComponent();
this.setState({
component: component[Object.keys(component)[0]]
});
}
My best guess is that I have not written this line properly in typescript:
const { default: component } = await importComponent();
I'm calling the asyncComponent method like so:
const MyComponent = asyncComponent(()=>import(./components/MyComponent));
Anyone know how to implement the AsyncComponent in typescript? I'm not sure if simply getting the 0 index on the esModule object is the correct way to do it.
// AsyncComponent.tsx
import * as React from "react";
interface AsyncComponentState {
Component: null | JSX.Element;
};
interface IAsyncComponent {
(importComponent: () => Promise<{ default: React.ComponentType<any> }>): React.ComponentClass;
}
const asyncComponent: IAsyncComponent = (importComponent) => {
class AsyncFunc extends React.PureComponent<any, AsyncComponentState> {
mounted: boolean = false;
constructor(props: any) {
super(props);
this.state = {
Component: null
};
}
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />
});
}
}
render() {
const Component = this.state.Component;
return Component ? Component : <div>....Loading</div>
}
}
return AsyncFunc;
}
export default asyncComponent;
// Counter.tsx
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
interface CounterState {
currentCount: number;
}
class Counter extends React.Component<RouteComponentProps<{}>, CounterState> {
constructor() {
super();
this.state = { currentCount: 0 };
}
public render() {
return <div>
<h1>Counter</h1>
<p>This is a simple example of a React component.</p>
<p>Current count: <strong>{this.state.currentCount}</strong></p>
<button onClick={() => { this.incrementCounter() }}>Increment</button>
</div>;
}
incrementCounter() {
this.setState({
currentCount: this.state.currentCount + 1
});
}
}
export default Counter;
//routes.tsx
import * as React from 'react';
import { Route } from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import asyncComponent from './components/AsyncComponent';
const AsyncCounter = asyncComponent(() => import('./components/Counter'));
export const routes = <Layout>
<Route exact path='/' component={Home} />
<Route path='/counter' component={AsyncCounter} />
</Layout>;

react-lifecycle-component have props in componentDidMount

I'm using react-lifecycle-component in my react app, and incurred in this situation where I need the componentDidMount callback to load some data from the backend. To know what to load I need the props, and I can't find a way to retrieve them.
here's my container component:
import { connectWithLifecycle } from "react-lifecycle-component";
import inspect from "../../../libs/inspect";
import fetchItem from "../actions/itemActions";
import ItemDetails from "../components/ItemDetails";
const componentDidMount = () => {
return fetchItem(props.match.params.number);
};
// Which part of the Redux global state does our component want to receive as props?
const mapStateToProps = (state, props) => {
return {
item: state.item,
user_location: state.user_location
};
};
// const actions = Object.assign(locationActions, lifecycleMethods);
export default connectWithLifecycle(mapStateToProps, { componentDidMount })(
ItemDetails
);
Any clues?
thanks.
import React, { Component } from 'react'
import { connect } from 'react-redux'
import fetchItem from '../actions/itemActions'
class Container extends Component {
state = {
items: []
}
componentDidMount() {
const { match } = this.props
fetchItem(match.params.number)
// if your fetchItem returns a promise
.then(response => this.setState({items: response.items}))
}
render() {
const { items } = this.state
return (
<div>
{ items.length === 0 ? <h2>Loading Items</h2> :
items.map((item, i) => (
<ul key={i}>item</ul>
))
}
</div>
)
}
const mapStateToProps = (state, props) => {
return {
item: state.item,
user_location: state.user_location
}
}
export default connect(mapStateToProps)(Container)
Though I don't see where you are using the props you take from your Redux store...

Resources