I am new in react and redux. I am fetching data from one page page and I would like to show details of the record. When I click from the list to see details for the first time, it is fine. But when I would like to see the next result details and for a millisecond there is a blink of previous result and then re rendered by the new one. Could you help me with this issue, please? I do not want to see the previous artist detail.
Show details
import React from 'react';
import { connect } from 'react-redux';
import { fetchArtistDetails } from '../../actions';
class ResultDetails extends React.Component{
componentDidMount(){
this.props.fetchArtistDetails(this.props.match.params.id);
}
renderList(){
return this.props.artist.map(artist => {
return(
<div className="ui segment">
<br/>
<div className="ui two column centered grid">
<div className="ui centered massive label">{artist.name}</div>
</div>
<br/>
<br/>
{ (artist.images) ?
artist.images.map(image =>{
return image.type ==='primary' ? <img className="ui centered medium image" src={image.uri}/> : null
}) : null
}
<div className="ui small images">
{ (artist.images) ?
artist.images.map(image =>{
return image.type ==='secondary' ? <img src={image.uri}/> : null
}) : null
}
</div>
<p>{artist.profile}</p>
</div>
);
});
}
render(){
if (!this.props.artist) {
console.log("ahoj");
return <div>Loading...</div>;
}
return(
<div>
<div>{this.renderList()}</div>
</div>
);
}
}
const mapStateToProps = state => {
return { artist: state.artistDetails }
}
export default connect( mapStateToProps , { fetchArtistDetails }) (ResultDetails);
Actions
import discogs from '../apis/discogs';
import history from '../history';
import { FETCH_POSTS, SEARCH_ARTIST, FETCH_ARTIST_DETAILS, CLEAN_ARTIST_DETAILS } from './types';
export const fetchPosts = text => async dispatch => {
const response = await discogs.get(`/database/search?q=${text}&type=artist`);
dispatch({ type: FETCH_POSTS, payload: response.data.results });
history.push(`/results/${text}`);
};
export const searchArtist = text => dispatch => {
dispatch({
type: SEARCH_ARTIST,
payload: text
});
};
export const fetchArtistDetails = id => async dispatch => {
const response = await discogs.get(`/artists/${id}`);
dispatch({ type: FETCH_ARTIST_DETAILS, payload: response.data });
history.push(`/details/${id}`);
};
Reducer
import {
FETCH_ARTIST_DETAILS,
} from '../actions/types';
export default (state = [], action) => {
switch (action.type) {
case FETCH_ARTIST_DETAILS:
return [action.payload]
default:
return state;
}
};
App
import React, { Fragment } from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import MainPage from '../pages/MainPage';
import SearchResult from '../components/searchResult/SearchResult';
import ResultDetails from '../components/resultDetails/ResultDetails';
import Header from './header/Header';
import history from '../history';
const App = () => {
return (
<div className="ui container">
<Router history={history}>
<div>
<Switch>
<Route exact path='/' component={MainPage} />
<Fragment>
<Header />
<Route exact path="/results/:id" component={SearchResult} />
<Route exact path="/details/:id" component={ResultDetails} />
</Fragment>
</Switch>
</div>
</Router>
</div>
);
};
export default App;
I found and issue (I do not know, if it is proper solution but it works for me)
New action
export const cleanArtistDetails = () => async dispatch => {
dispatch({ type: CLEAN_ARTIST_DETAILS, payload: null });
};
Update reducer
import {
FETCH_ARTIST_DETAILS, CLEAN_ARTIST_DETAILS,
} from '../actions/types';
export default (state = [], action) => {
switch (action.type) {
case FETCH_ARTIST_DETAILS:
return [action.payload]
case CLEAN_ARTIST_DETAILS:
return null
default:
return state;
}
};
And update component
componentWillUnmount(){
this.props.cleanArtistDetails();
}
Related
// I am working on Login/Register from in React and I am using firebase auth for
authentication. When the user logged in I want to redirect the user on the root path or
on App component. But I got into an infinite loop which gives me this error (#Throttling
navigation to prevent the browser from hanging.#)//
**App Js**
import { useEffect } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import "./App.css";
import Header from "./components/Header";
import Home from "./components/Home";
import Login from "./components/Login";
import { getUserAuth } from "./actions";
import { connect } from "react-redux";
function App(props) {
useEffect(() => {
props.getUserAuth();
}, []);
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Login />} />
<Route
path="/home"
element={
<>
<Header />
<Home />
</>
}
/>
</Routes>
</BrowserRouter>
</div>
);
}
const mapStateToProps = (state) => {
return {};
};
const mapDispatchToProps = (dispatch) => ({
getUserAuth: () => dispatch(getUserAuth()),
});
export default connect(mapStateToProps, mapDispatchToProps)(App);
//App Section End//
**LogIn**
import styled from "styled-components";
import { connect } from "react-redux";
import { signInAPI } from "../actions";
import { Navigate } from "react-router-dom";
const Login = (props) => {
return (
<Container>
{props.user && <Navigate to="/home" />}
<Nav>
<a href="/">
<img src="/images/login-logo.svg" alt="" />
</a>
<div>
<Join>Join now</Join>
<SignIn>Sign in</SignIn>
</div>
</Nav>
<Section>
<Hero>
<h1>Welcome to your professional community</h1>
<img src="/images/login-hero.svg" alt="" />
</Hero>
<Form>
<Google onClick={() => props.signIn()}>
<img src="/images/google.svg" alt="" />
Sign in with Google
</Google>
</Form>
</Section>
</Container>
);
};
const mapStateToProps = (state) => {
return {
user: state.userState.user,
};
};
const mapDispatchToProps = (dispatch) => ({
signIn: () => dispatch(signInAPI()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
//LogIn Section End to identify the error //
**SignIn**
import { auth, provider } from "../firebase";
import { signInWithPopup, onAuthStateChanged, signOut } from "firebase/auth";
import { SET_USER } from "./actionType";
export const setUser = (payload) => ({
type: SET_USER,
user: payload,
});
export function signInAPI() {
return (dispatch) => {
signInWithPopup(auth, provider)
.then((payload) => {
// console.log(payload.user);
dispatch(setUser(payload.user));
})
.catch((error) => alert(error.message));
};
}
export function getUserAuth() {
return (dispatch) => {
onAuthStateChanged(auth, (user) => {
console.log(user);
if (user) {
dispatch(setUser(user));
}
});
};
}
export function signOutAPI() {
return (dispatch) => {
signOut(auth)
.then(() => {
dispatch(setUser(null));
})
.catch((error) => {
console.log(error.message);
});
};
}
**End SignIn**
//**Throttling navigation** to prevent the browser from hanging.//
//Warning: Maximum update depth exceeded. This can happen when a component calls
setState inside useEffect, but useEffect either doesn't have a dependency array, or
one of the dependencies changes on every render. Unable to identify the error //
Note: please pull the repo to get access to the full App, there are too many files to simply share the code here. The repo: https://github.com/liviu-ganea/movie-database.git
So I've asked a question previously about my first React + Redux app and I've improved it. I got 2 problems now. The delete function for each movie (i.e. each entry in the redux state) is working just fine. So I now have problems with Login. Every time I press the button, nothing happens, and I suspect it's because the Login page component receives no props from the redux state.
My reasoning:
handleCLick = () => {
let userName = this.props.user.nickname;
let pw = this.props.user.password;
const nicknameBox = document.getElementById('nickname').textContent;
const passwordBox = document.getElementById('password').textContent.trim;
/*if (nicknameBox === userName && passwordBox === pw) {*/
this.props.loginUser((this.props.user.isLoggedIn = true));
this.props.history.push('/');
//}
};
When commented as it is now, it should go to the home page whenever I click the login button and if the password matches doesn't matter. Only there is no reaction to me pressing the button. Is the problem as I suspect?
And another problem: see in Movie.js I've tried to get the path (it's set in state: movies: cover) to the movie poster (located in ./src) so that when (or if) I make use of an API the path should set itself dynamically (i.e. I won't have to go into every component and add the path manually). Same thing on the Home page (./src/Components/Routes/Home.js)...no posters for any movie.
After Comments:
Component:
import React, { Component } from 'react';
import './routes.css';
import { loginAction } from '../../actions/userActions';
import { connect } from 'react-redux';
class Login extends Component {
handleCLick = () => {
let userName = this.props.user.nickname;
let pw = this.props.user.password;
const nicknameBox = document.getElementById('nickname').textContent;
const passwordBox = document.getElementById('password').textContent.trim;
/*if (nicknameBox === userName && passwordBox === pw) {*/
this.props.loginUser((this.props.user.isLoggedIn = true));
this.props.history.push('/');
//}
};
render() {
console.log(this.props);
return (
<div className="container page-container login-page">
<h3 className="page-title">Log In User</h3>
<div className="login-box">
<div>
<label className="login-labels" htmlFor="nickname">
Login{' '}
</label>
<input type="text" className="nickname-box" name="nickname" id="nickname" />
</div>
<div>
<label className="login-labels" htmlFor="password">
Password{' '}
</label>
<input type="password" className="password-box" name="password" id="pasword" />
</div>
<button className="login-button" onClick={this.handleClick}>
Login
</button>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
user: state.user,
};
};
const mapDispatchToProps = (dispatch) => {
return {
loginUser: (isLoggedIn) => {
dispatch(loginAction(isLoggedIn));
},
};
};
export default connect(mapDispatchToProps, mapStateToProps)(Login);
Reducer:
import { createStore } from 'redux';
const initialState = {
movies: [
{
id: '1',
title: 'John Wick Chapter 2',
year: '2017',
main_actor: 'Keanu Reeves',
summary: `The hitman that's been retired then back then retired strikes again, this time against the Mafia.`,
cover: '../john_wick_2.jpg',
},
{
id: '2',
title: 'Star Wars Revenge of the Sith',
year: '2005',
main_actor: 'Ewan McGregor',
summary: `Anakin betrays Space Jesus so General Kenobi is forced to Mustafar Anakin.`,
cover: '../sw_rots.png',
},
{
id: '3',
title: 'Star Wars The Clone Wars',
year: '2008 - 2020',
main_actor: 'Ewan McGregor, Hayden Christensen',
summary: `Yoda has finally overdosed on Ketamine, Mace Window hasn't been defenestrated yet and The Negotiator has proven himself incapable of falling to the Dark Side`,
cover: '../sw_tcw.jpg',
},
],
user: {
isLoggedIn: 'false',
nickname: 'obi_wan',
password: '12345',
},
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'DELETE_MOVIE':
let newMovieList = state.movies.filter((movie) => {
return action.id !== movie.id;
});
return {
...state,
movies: newMovieList,
};
case 'LOG_IN':
let newUserState = action.isLoggedIn;
return {
...state,
user: { ...state.user, isLoggedIn: action.payload.isLoggedIn },
};
default:
return state;
}
return state;
};
export default rootReducer;
userActions:
export const loginAction = (isLoggedIn) => {
return {
type: 'LOG_IN',
isLoggedIn: 'true',
};
};
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers/rootReducer';
import App from './App';
const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);
console.log(this.props) for the Login component:
[![enter image description here][1]][1]
Movie.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { deleteMovieAction } from '../actions/movieActions';
import './Routes/routes.css';
class Movie extends Component {
handleClick = () => {
this.props.deleteMovie(this.props.movie.id);
this.props.history.push('/');
};
render() {
console.log(this.props);
const isUser = this.props.user.isLoggedIn ? (
<button className="delete-movie-button" onClick={this.handleClick}>
Delete
</button>
) : null;
const theMovie = this.props.movie ? (
<div className="movie-container">
<img src={this.props.movie.cover} alt={this.props.movie.title} className="movie-cover" />
<div className="movie-container-content">
<h2 className="movie-title">{this.props.movie.title}</h2>
<p className="movie-description">{this.props.movie.summary}</p>
<div className="movie-data">
<p className="movie-year">{this.props.movie.year}</p>
<p className="movie-actor">{this.props.movie.main_actor}</p>
</div>
</div>
{isUser}
</div>
) : (
<div className="center">Getting data about the movie. Please wait.</div>
);
return <div className="container page-container">{theMovie}</div>;
}
}
const mapStateToProps = (state, ownProps) => {
let id = ownProps.match.params.movie_id;
return {
user: state.user,
movie: state.movies.find((movie) => movie.id === id),
};
};
const mapDispatchToProps = (dispatch) => {
return {
deleteMovie: (id) => {
dispatch(deleteMovieAction(id));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Movie);
Movie.js - every movie component
import React, {Component} from 'react'
import { connect } from 'react-redux';
import { deleteMovieAction } from '../actions/movieActions'
import './Routes/routes.css'
class Movie extends Component {
handleClick = () => {
this.props.deleteMovie(this.props.movie.id);
this.props.history.push('/');
}
render () {
const coverino = ''
console.log(this.props);
const isUser = this.props.isLoggedIn ? ( <button className='delete-movie-button' onClick={this.handleClick}>Delete</button> ) : (null)
const theMovie = this.props.movie ? (
<div className='movie-container'>
<img src={this.props.movie.cover} alt={this.props.movie.title} className='movie-cover'/>
<div className='movie-container-content'>
<h2 className='movie-title'>{this.props.movie.title}</h2>
<p className='movie-description'>{this.props.movie.summary}</p>
<div className='movie-data'>
<p className='movie-year'>{this.props.movie.year}</p>
<p className='movie-actor'>{this.props.movie.main_actor}</p>
</div>
</div>
{isUser}
</div>
) : ( <div className="center">Getting data about the movie. Please wait.</div> );
return (
<div className='container page-container'>
{theMovie}
</div>
)
}
}
const mapStateToProps = (state, ownProps) => {
let id = ownProps.match.params.movie_id;
return {
isLoggedIn: state.user.isLoggedIn,
movie: state.movies.find(movie => movie.id === id),
}
}
const mapDispatchToProps = (dispatch) => {
return {
deleteMovie: (id) => { dispatch(deleteMovieAction(id))}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Movie)
The page display the entire movie list
import React, {Component} from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import './routes.css'
class Home extends Component{
render() {
console.log(this.props);
const { movies } = this.props;
const movieList = movies.length ? ( movies.map(movie => {
return (
<Link to={'/' + movie.id} key={movie.id}>
<div className='movie-container'>
<img src={require(`${movie.cover}`)} alt={movie.title} className='movie-cover'/>
<div className='movie-container-content'>
<h2 className='movie-title'>{movie.title}</h2>
<p className='movie-description'>{movie.summary}</p>
<div className='movie-data'>
<p className='movie-year'>{movie.year}</p>
<p className='movie-actor'>{movie.main_actor}</p>
</div>
</div>
</div>
</Link>
)
}
, )) : (<div className='waiting-for-movies'>Loading. Please wait</div>)
return (
<div className='container page-container'>
{movieList}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
movies: state.movies
}
}
export default connect(mapStateToProps)(Home)
neither the require method, nor the simple {this.props...} works
[1]: https://i.stack.imgur.com/51FTy.png
I am creating my first react project, i am using GitHub api to fetch user and display them firstly in card view then on clicking on more button to any profile i want to create a modal using portals in react till now i am able to create an modal but now i am not getting how to get data to that modal coponent
Here is my App.js
import React, { Fragment, Component } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Navbar from './components/layout/Navbar';
import Users from './components/users/Users';
import User from './components/users/User';
import Modal from './components/Modal/Modal'
import Search from './components/users/Search';
import Alert from './components/layout/Alert';
import About from './components/pages/About';
import axios from 'axios';
import './App.css';
class App extends Component {
state = {
users: [],
user: {},
loading: false,
alert: null,
modal: {},
}
// get users from Search.js
searchUsers = async text => {
this.setState({ loading: true })
const res = await axios.get(
`https://api.github.com/search/users?q=${text}&client_id=${
process.env.REACT_APP_GITHUB_CLIENT_ID
}&client_secret=${process.env.REACT_APP_GITHUB_CLIENT_SECRET}`);
this.setState({ users: res.data.items, loading: false })
console.log(text);
}
//get single profile
getUser = async username => {
this.setState({ loading: true })
const res = await axios.get(
`https://api.github.com/users/${username}?client_id=${
process.env.REACT_APP_GITHUB_CLIENT_ID
}&client_secret=${process.env.REACT_APP_GITHUB_CLIENT_SECRET}`);
this.setState({ user: res.data, loading: false });
this.setState({ modal: res.data, loadading: false });
}
//clear search
clearUsers = () => this.setState({ users: [], loading: false });
setAlert = (msg, type) => {
this.setState({ alert: { msg: msg, type: type } });
setTimeout(() => this.setState({ alert: null }), 5000);
};
render() {
return (
<Router>
<div className='App'>
<Navbar />
<div className="container">
<Alert alert={this.state.alert} />
<Switch>
<Route exact path='/'
render={props => (
<Fragment>
<Search
searchUsers={this.searchUsers}
clearUsers={this.clearUsers}
showClear={this.state.users.length > 0 ? true : false}
setAlert={this.setAlert}
/>
<Users loading={this.state.loading} users={this.state.users} />
</Fragment>
)} />
<Route path='/about' component={About} />
<Route path='/user/:login' render={props => (
<User {...props} getUser={this.getUser} user={this.state.user} loading={this.state.loading} />
)} />
<Route path='/modal/:login' render={props => (
<Modal {...props} getUser={this.getUser} modal={this.state.modal} loading={this.state.loading} />
)} />
</Switch>
</div>
</div>
</Router>
);
}
}
export default App;
here is my Modal.js
import React, { Fragment, Component } from 'react';
import ReactDom from 'react-dom';
import Spinner from '../layout/Spinner';
import { Link } from 'react-router-dom';
const modalRoot = document.getElementById('modal');
export default class Modal extends Component {
constructor() {
super();
this.el = document.createElement('div');
}
componentDidMount = () => {
modalRoot.appendChild(this.el);
};
componentWillUnmount = () => {
modalRoot.removeChild(this.el);
};
render() {
const {
children,
name,
avatar_url,
location,
bio,
blog,
followers,
following,
public_repos,
} = this.props.modal;
const { loading } = this.props;
if (loading) return <Spinner />
return (
ReactDom.createPortal(children, this.el)
)
}
}
any guide would be appriciated thanks in advance
You are passing the props already to Modal.
In Modal, do something like
Class Modal extends Component {
constructor(){
super(props);
}
render(){
const {
modal,
getUser,
loading,
anyOtherPropYouPassIn
} = this.props;
const { loading } = this.props;
if (loading) return <Spinner />
return (
ReactDom.createPortal(children, this.el)
)
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I wrote a react redux app, everyting working fine, now i am trying implement my initial data should be comes from API endpoint,
this is my postReducers.py file:
var initialState = {
employees: []
};
var postReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_POST':
return {
...state,
employees: [...state.employees, action.data],
};
case 'EDIT_POST':
return {
...state,
employees: state.employees.map(emp => emp.id === action.data.id ? action.data : emp)
};
case 'DELETE_POST':
console.log(action.data.id)
return {
...state,
employees: [...state.employees.filter((post)=>post.id !== action.data.id)],
};
default:
return state;
}
};
export default postReducer;
and this is my table.js file
import React, {Fragment} from "react";
import { connect } from "react-redux";
const axios = require('axios');
class Table extends React.Component {
onEdit = (item) => { //Use arrow function to bind `this`
this.props.selectedData(item);
}
onDelete = (id) => {
const data = {
id,
}
this.props.dispatch({ type: 'DELETE_POST', data });
}
render() {
return (
<Fragment>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.props.employees.map((item, index) => (
<tr key={index}>
<td>{item.name}</td>
<td>{item.age}</td>
<td>
<button
type="button"
onClick={() => this.onEdit(item)}>EDIT
</button>
<button
onClick={ () => this.onDelete(item.id) }>DELETE
</button>
</td>
</tr>
))}
</tbody>
</Fragment>
);
}
}
const mapStateToProps = (state) => ({ employees: state.employees });
export default connect(mapStateToProps)(Table);
and this is my App.js file
import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Home from '../components/home'
import Contacts from '../components/contact'
import About from '../components/about'
class App extends Component {
render() {
return (
<Router>
<p>A simple webpack for django and react</p>
<div>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<ul className="navbar-nav mr-auto">
<li><Link to={'/'} className="nav-link"> Home </Link></li>
<li><Link to={'/contact'} className="nav-link">Contact</Link></li>
<li><Link to={'/about'} className="nav-link">About</Link></li>
</ul>
</nav>
<hr />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/contact' component={Contacts} />
<Route path='/about' component={About} />
</Switch>
</div>
</Router>
);
}
}
export default App;
and this is my home.js file
import React from "react"
import Table from "../components/table"
import Form from '../components/form'
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedData: {name: '', age: ''},
isEdit: false
};
}
selectedData = (item) => {
this.setState({selectedData: item,isEdit:true})
}
render() {
return (
<React.Fragment>
<Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>
<table>
<Table selectedData={this.selectedData} />
</table>
</React.Fragment>
);
}
}
export default Home;
this is my Form.js file:
import React, { Fragment } from "react"
import { connect } from 'react-redux'
const axios = require('axios');
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.selectedData.id,
name: this.props.selectedData.name,
age: this.props.selectedData.age,
};
this.onHandleChange = this.onHandleChange.bind(this);
this.submit = this.submit.bind(this);
}
submit(event) {
const data = {
name: this.state.name,
age: this.state.age,
email: this.state.email
};
if (this.props.isEdit) {
data.id = this.props.selectedData.id;
console.log('edit', data);
this.props.dispatch({ type: 'EDIT_POST', data })
} else {
// generate id here for new emplyoee
this.props.dispatch({ type: 'ADD_POST', data })
}
}
onHandleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
componentDidUpdate(prevProps) {
if (prevProps.selectedData.age !== this.props.selectedData.age) { //Check on email, because email is unique
this.setState({ name: this.props.selectedData.name, age: this.props.selectedData.age })
}
}
render() {
return (
<form>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.name} name="name" type="text" />
</div>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.age} name="age" type="number" />
</div>
<button onClick={(event) => this.submit(event)} type="button">
{this.props.isEdit ? 'Update' : 'SAVE'}
</button>
</form>
);
}
}
export default connect(null)(Form);
and this is my index.js file:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom'
import App from "../client/components/App";
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import postReducer from '../client/postReducer'
const store = createStore(postReducer)
// if we don't subcribe, yet our crud operation will work
function onStateChange() {
const state = store.getState();
}
store.subscribe(onStateChange)
ReactDOM.render((
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
), document.getElementById('app'))
Can anyone please help me to implement my initialState, so that when i visit the page or whe the table is loaded, the table should get data from API end point?
My API End point is: http://127.0.0.1:8000/employees/ it has only two field, name, and age
I am using axios for http request
I searched on stackoverflow and a man showed a possible duplicate post but that didnt solve my problem, coz, it was for react native
You can fetch the data in your home.js where you are using your Table component. You can fetch the data in componentDidMount() and pass data to your reducer using an action like SET_EMPLOYEES_LIST:
home.js:
import React from "react"
import Table from "../components/table"
import Form from '../components/form'
import { setEmployeesList } from './actions'
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedData: {name: '', age: ''},
isEdit: false
};
}
componentDidMount(){
Axios.get(URL).then(res => this.props.setEmployeesList(res.data))
}
selectedData = (item) => {
this.setState({selectedData: item,isEdit:true})
}
render() {
return (
<React.Fragment>
<Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>
<table>
<Table selectedData={this.selectedData} />
</table>
</React.Fragment>
);
}
}
const mapDispatchToProps = dispatch => {
return {
setEmployeesList: data => dispatch(setEmployeesList(data)) // Set the action you created in your component props
}
}
export default Home;
action.js:
import {SET_EMPLOYEES_LIST} from './constants'
export const setEmployeesList = payload => ({ type: SET_EMPLOYEES_LIST, payload })
constants.js:
export const SET_EMPLOYEES_LIST = 'SET_EMPLOYEES_LIST'
postReducers.js:
import {SET_EMPLOYEES_LIST} from './constants'
const initialState = {
employees: []
};
const postReducer = (state = initialState, action) => {
switch (action.type) {
case SET_EMPLOYEES_LIST:
return {
...state,
employees: action.payload,
};
case 'ADD_POST':
return {
...state,
employees: [...state.employees, action.data],
};
case 'EDIT_POST':
return {
...state,
employees: state.employees.map(emp => emp.id === action.data.id ? action.data : emp)
};
case 'DELETE_POST':
console.log(action.data.id)
return {
...state,
employees: [...state.employees.filter((post)=>post.id !== action.data.id)],
};
default:
return state;
}
};
export default postReducer;
I used to make this code work out for my search component but after the on submit is called, I receive this error which never happened before, does anyone have any clue???
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
import React, { Component } from "react";
import axios from "axios";
import { Redirect } from "react-router-dom";
import { Consumer } from "../context";
class Search extends Component {
constructor() {
super();
this.state = {
productTitle: "",
apiUrl: "*******************************",
redirect: false
};
}
findProduct = (dispatch, e) => {
e.preventDefault();
axios
.post(
`${this.state.apiUrl}`,
JSON.stringify({ query: this.state.productTitle })
)
.then(res => {
dispatch({
type: "SEARCH_TRACKS",
payload: res.data.output.items
});
this.setState({ items: res.data.output.items, redirect: true });
})
.catch(err => console.log(err));
};
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
render() {
const { redirect } = this.state;
if (redirect) {
return <Redirect to="/searchresult" />;
}
return (
<Consumer>
{value => {
const { dispatch } = value;
return (
<div>
<form onSubmit={this.findProduct.bind(this, dispatch)}>
<div className="form-group" id="form_div">
<input
type="text"
className="form-control form-control-md"
placeholder="...محصولات دسته یا برند مورد نظرتان را انتخاب کنید"
name="productTitle"
value={this.state.productTitle}
onChange={this.onChange}
/>
<button className="btn" type="submit">
<i className="fas fa-search" />
</button>
</div>
</form>
</div>
);
}}
</Consumer>
);
}
}
import React, { Component } from 'react'
import axios from 'axios'
const Context = React.createContext();
export const axiosDashboard = () => {
const URL = (`*****************`);
return axios(URL, {
method: 'POST',
data: JSON.stringify({refresh:"true"}),
})
.then(response => response.data)
.catch(error => {
throw error;
});
};
const reducer = (state, action) => {
switch(action.type){
case 'SEARCH_TRACKS':
return {
...state,
items: action.payload,
heading: 'Search Results'
};
default:
return state;
}
}
export class Provider extends Component {
state = {
dispatch:action => this.setState(state => reducer(state, action))
}
render() {
return (
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer = Context.Consumer
import React, { Component } from 'react'
import { Consumer } from '../context'
import SearchResult from './SearchResult'
import './Search.css'
class Tracks extends Component {
render() {
return (
<Consumer>
{value => {
const { items } = value
if(items === undefined || items.length === 0){
return 'hello'}
else{
return(
<React.Fragment>
<div id='products_search'>
<div className='container'>
<div className="row justify-content-end">
{items.map(item => (
<SearchResult
key={item.id}
id={item.id}
title={item.name}
current_price={item.current_price}
lowest_price={item.lowest_price}
store_name={item.store_name}
thumb={item.thumb_url}/>
))}
</div>
</div>
</div>
</React.Fragment>
)
}
}}
</Consumer>
)
}
}
export default Tracks
import React from 'react'
import {Link} from 'react-router-dom'
import './Search.css'
const SearchResult = (props) => {
const {title,current_price,lowest_price,thumb,id,store_name} = props
return (
<div className="col-md-3" id="searchresult">
<img src={thumb} alt=""/>
<div className="sexy_line"></div>
<p className="muted">{store_name}</p>
<h6>{title}</h6>
<p>{lowest_price}</p>
<Link to={`products/item/${id}`}>
<button type="button" className="btn btn-light rounded-pill">{
new Intl
.NumberFormat({style: 'currency', currency: 'IRR'})
.format(current_price)
}</button>
</Link>
</div>
)
}
export default SearchResult
Maximum update depth exceeded.
This means that you are in a infinit loop of re rendering a component.
The only place where I can see this is possible to happen is in this part
if (redirect) {
return <Redirect to="/searchresult" />;
}
Maybe you are redirecing to the a route that will get the same component that have the redirect.
Please check if you aren't redirecting to the same route as this component and provide your routes and what is inside Consumer.