Sorry for my bad english and my bad logic, i wanted use pokeapi.co for my Pokedex.
My problem : i need display the props who content the informations from api. I can receive informations in my console.log(response) on my axios request, but i can not display them on a list on my Nav component, where are my errors ?
The endPoint : https://pokeapi.co/api/v2/pokemon
My code :
App.js
// == Import : npm
import React from 'react';
// == Import : local
import Home from 'src/components/Home';
import Nav from 'src/containers/Nav';
import './app.scss';
// == Composant
const App = results => (
<div id="app">
<nav className="nav">
<Nav props={results} />
</nav>
<main className="content">
<Home />
</main>
)}
</div>
);
// == Export
export default App;
reducer.js
// == Initial State
const initialState = {
results: [],
name: '',
url: '',
};
// == Types
export const FETCH_POKEMON_API = 'FETCH_POKEMON_API';
const RECEIVE_POKEMON_LIST = 'RECEIVE_POKEMON_LIST';
// == Reducer
const reducer = (state = initialState, action = {}) => {
// console.log('une action arrive dans le reducer', action);
switch (action.type) {
case RECEIVE_POKEMON_LIST:
return {
...state,
results: action.results,
};
default:
return state;
}
};
// == Action Creators
export const fetchPokemonApi = () => ({
type: FETCH_POKEMON_API,
});
export const receivePokemonList = results => ({
type: RECEIVE_POKEMON_LIST,
results,
});
// == Selectors
// == Export
export default reducer;
Nav Component
import React from 'react';
import PropTypes from 'prop-types';
// import { NavLink } from 'react-router-dom';
// import { getUrl } from 'src/utils';
import './nav.scss';
const Nav = ({ results }) => {
console.log('if i receive my props from PokeAPI its win guys', results);
return (
<div className="menu">
{results.map(({ Pokemon }) => (
<li key={Pokemon} className="menu-item">
{Pokemon}
</li>
))}
</div>
);
};
Nav.propTypes = {
results: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
}),
).isRequired,
};
export default Nav;
Nav Container
// == Import : npm
import { connect } from 'react-redux';
// == Import : local
import Nav from 'src/components/Nav';
// === State (données) ===
const mapStateToProps = state => ({
results: state.results,
});
// === Actions ===
const mapDispatchToProps = {};
// Container
const NavContainer = connect(
mapStateToProps,
mapDispatchToProps,
)(Nav);
// == Export
export default NavContainer;
axiosMiddleware
import axios from 'axios';
import { FETCH_POKEMON_API, receivePokemonList } from 'src/store/reducer';
const ajaxMiddleware = store => next => (action) => {
console.log('L\'action suivante tente de passer', action);
switch (action.type) {
case FETCH_POKEMON_API:
axios.get('https://pokeapi.co/api/v2/pokemon')
.then((response) => {
console.log('response', response);
console.log('response.data', response.data);
console.log('response.data.results', response.data.results);
const { data: results } = response;
this.setState({
results: response.data.results,
});
store.dispatch(receivePokemonList(results));
})
.catch(() => {
console.log('Une erreur s\'est produite');
});
break;
default:
// console.log('action pass', action);
next(action);
}
};
export default ajaxMiddleware;
whats wrong ?
Thanks you !
Thanks to #Meshack Mbuvi for his support in private.
The abscence of thunk is the first problem
The following code resolved my problem ( thanks to #Mbuvi ) :
axios.get('https://pokeapi.co/api/v2/pokemon')
.then((response) => {
console.log('response.data.results', response.data.results);
// ici je défni pokemons from api, qui contient la list des pokemons
// It was like this: const {results} = response.data.results
const { results } = response.data; // The error was here
dispatch(receivePokemonList(results));
})
.catch((err) => {
console.log('Une erreur s\'est produite', err);
});
};
I am thinking the code is failing because initially, the results are undefined(Before the call to the API). Also, your Nav component requires that your result object should have a property named name.
Have your initial state as follows:
const initialState = {
results: [{name:""}],
name: '',
url: '',
};
Let me know what how it goes
Using Lodash
{
_.map(results, (Pokemon, index) => {
return (
<li key={Pokemon} className="menu-item">
{Pokemon}
</li>
)})
}
Using Native Map
{
results.map((Pokemon, index) => {
return (
<li key={Pokemon} className="menu-item">
{Pokemon}
</li>
)})
}
I think you forgot to return the map component.
Related
I've started to learn Redux with React, I got stuck in a part of my project which is a movies store that when the user chooses the number of tickets and clicks on add to cart I want to update the quantity and add the movie to the bag.
I implemented some redux in my code but the functionalities are not working?
What do you think?
<-- Constant-->
export const ActionsTypes = {
SET_MOVIES : "SET_MOVIES",
GET_MOVIE : "GET_MOVIE",
REMOVE_MOVIE : "REMOVE_MOVIE",
QUANTITY: "QUANTITY",
ADD_PRODUCT : "ADD_PRODUCT",
}
<-- My Actions -->
import {ActionsTypes} from "../Constants/ActionsTypes";
// create actions functions
export const setMovies = (movies)=> {
return {
type : ActionsTypes.SET_MOVIES,
payload : movies,
}
}
export const getMovie = (movie) => {
return {
type : ActionsTypes.GET_MOVIE,
payload: movie,
}
}
export const removeMovie = () => {
return {
type : ActionsTypes.REMOVE_MOVIE,
}
}
export const AddProduct = (singleMovie) => {
return {
type : ActionsTypes.ADD_PRODUCT,
payload: singleMovie,
}
}
<-- Reducers --->
import { ActionsTypes } from "../Constants/ActionsTypes";
const initialState = {
movies: [],
quantity :0,
};
// Reducers function takes two arguments state, action
//Movies Reducers
export const setMoviesReducers = (state = initialState, action) => {
switch (action.type) {
case ActionsTypes.SET_MOVIES:
return {...state, movies: action.payload }
default:
return state;
}
}
// single Movies Reducers
export const GetMovieDetailsReducers = (state={}, action) => {
switch(action.type) {
case ActionsTypes.GET_MOVIE :
return {...state, ...action.payload}
case ActionsTypes.REMOVE_MOVIE :
return {};
default :
return state;
}
}
// Add to card and Quatity reducers
export const AddMovieToCart = (state = initialState, action) => {
switch (action.type) {
case ActionsTypes.ADD_PRODUCT :
return {...state, quantity: state.quantity+1, products:[...state.products,action.payload]};
default :
return state;
}
}
<-- Combine reducers-->
import {combineReducers} from "redux";
import { setMoviesReducers, GetMovieDetailsReducers, AddMovieToCart} from "./MoviesReducers";
export const reducers = combineReducers({
allMovies : setMoviesReducers,
movie : GetMovieDetailsReducers,
addToCart : AddMovieToCart,
});
<-- Movie details component-->
import React, {useEffect, useState} from 'react'
import { Add, Remove } from '#material-ui/icons';
import './MovieDetails.css';
import { useSelector, useDispatch } from 'react-redux';
import { useParams } from 'react-router';
import { getMovie, removeMovie, AddProduct} from '../../Redux/Actions/Actions';
import axios from 'axios';
const MovieDetails = () => {
const [quantity, setQuantity] = useState(1)
const singleMovie = useSelector((state)=> state.movie);
const addToCardProduct = useSelector((state)=> state.addToCart);
console.log(addToCardProduct);
const {title, poster_path, overview} = singleMovie;
const dispatch = useDispatch();
let {movieId} = useParams();
console.log(movieId);
// Handle Quantity
const handleQuantity = (type) => {
if(type === "dec") {
quantity > 1 && setQuantity(quantity - 1)
} else {
setQuantity(quantity + 1)
}
}
// add to cart Handler
const CartHandler = () => {
dispatch(addToCardProduct);
}
// Get a single Product & Remove product
useEffect(()=> {
try {
const getSingleMovie = async () => {
const request = await axios.get(`https://api.themoviedb.org/3/movie/${movieId});
const response = await request.data;
dispatch(getMovie(response))
}
getSingleMovie();
} catch(error) {
console.log(`ERROR : ${error}`)
}
//Clean up
return () => {
dispatch(removeMovie());
}
}, [movieId])
return (
<section className="movieDetails_container">
<div className="wrapper">
<div className="img-container">
<img src={`${ImgPath}` + poster_path} alt={title}/>
</div>
<div className="info-container">
<h1>{title}</h1>
<p>{overview}</p>
<div className="quantity-container">
<Remove className="quantity-icon" onClick={()=> handleQuantity("dec")}/>
<span className="amount">{quantity}</span>
<Add className="quantity-icon" onClick={()=> handleQuantity("incr")}/>
</div>
<button className="btn-add" onClick={CartHandler} >Add To Cart</button>
</div>
</div>
</section>
)
}
export default MovieDetails
<---Navbar where I have my bag icon and where I want to show the quantity-->
import React from 'react'
import './Navbar.css';
import { Link } from 'react-router-dom';
import { Badge } from '#material-ui/core';
import { LocalMall } from '#material-ui/icons';
import { useSelector } from 'react-redux';
const Navbar = () => {
const quantityBag = useSelector((state)=> state.quantity);
return (
<nav className="navBar-section">
<Link to="/">
<div className="logo-container">
<img className="logo" src="./Pictures/warner-bros.png" alt="Logo"/>
</div>
</Link>
<Badge badgeContent={0} color="primary">
<LocalMall className="icon-bag" />
</Badge>
</nav>
)
}
export default Navbar
I am learning React/Redux and I am trying to refactor this code from class-based to functional/hooks-based code. The application is an exercise I am working on, it has three components Posts.js where I fetch a list of posts from typicode.com. Each post from the fetched list has a button attacked.
On onClick, it should show details for each post (PostDetails.js and Comments.js):
At the moment, both Posts and Comments are class-based components. I need to:
Step 1: Change them to be functional components and use React Hooks but still keep connect(), mapStateToProps and mapDispatchToProps;
Step 2: Implement React-Redux hooks (UseSelector, useDispatch)
App.js
//imports...
const App = () => {
return (
<div className="container">
<div><Posts /></div>
<div><PostDetails /></div>
</div>
)
}
export default App;
actions
import jsonPlaceholder from '../apis/jsonPlaceholder';
export const fetchPosts = () => async dispatch => {
const response = await jsonPlaceholder.get('/posts');
dispatch({type: 'FETCH_POSTS', payload: response.data})
};
export const selectPost = post => {
return ({
type: 'POST_SELECTED',
payload: post
})
}
export const fetchComments = (id) => async dispatch => {
const response = await jsonPlaceholder.get(`/comments?postId=${id}`);
dispatch({type: 'FETCH_COMMENTS', payload: response.data})
}
reducers
export default (state = [], action) => {
switch (action.type) {
case 'FETCH_POSTS':
return action.payload;
default:
return state;
}
}
export default (selectedPost = null, action) => {
if (action.type === 'POST_SELECTED') {
return action.payload;
}
return selectedPost;
}
export default (state = [], action) => {
switch (action.type) {
case 'FETCH_COMMENTS':
return action.payload;
default:
return state;
}
}
export default combineReducers({
posts: postsReducer,
selectedPost: selectedPostReducer,
comments: commentsReducer
})
components/Posts.js
import React from 'react';
import { connect } from 'react-redux';
import { fetchPosts, selectPost } from '../actions';
import '../styles/posts.scss';
class Posts extends React.Component {
componentDidMount() {
this.props.fetchPosts()
}
renderPosts() {
return this.props.posts.map(post => {
if (post.id <= 10)
return (
<div className='item' key={post.id}>
<div className="title">
<h4>{post.title}</h4>
</div>
<button
onClick={() => {
this.props.selectPost(post)
console.log(post)
}
}>Open</button>
<hr/>
</div>
)
})
}
render() {
return(
<div className="list">
{ this.renderPosts() }
</div>
)
}
}
const mapStateToProps = state => {
return {
posts: state.posts,
selectedPost: state.post
}
};
const mapDispatchToProps = {
fetchPosts,
selectPost
}
export default connect(mapStateToProps, mapDispatchToProps)(Posts);
components/PostDetails.js
import React from 'react';
import { connect } from 'react-redux';
import Comments from './Comments'
const PostDetails = ({ post }) => {
if (!post) {
return <div>Select a post</div>
}
return (
<div className="post-details">
<div className="post-content">
<h3>{post.title}</h3>
<p>{post.body}</p>
<hr/>
</div>
<div className="comments-detail">
<Comments postId={post.id}/>
</div>
</div>
)
}
const mapStateToProps = state => {
return {post: state.selectedPost}
}
export default connect(mapStateToProps)(PostDetails);
components/Comments.js
import React from 'react';
import { connect } from 'react-redux';
import { fetchComments } from '../actions'
class Comments extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.postId && this.props.postId !== prevProps.postId){
this.props.fetchComments(this.props.postId)
}
}
renderComments() {
console.log(this.props.comments)
return this.props.comments.map(comment => {
return (
<div className="comment" key={comment.id}>
<div className="content">
<h5>{comment.name}</h5>
<p>{comment.body}</p>
</div>
<hr />
</div>
)
})
}
render() {
return (
<div className="comments">
{this.renderComments()}
</div>
)
}
}
const mapStateToProps = state => {
return {comments: state.comments}
}
export default connect(mapStateToProps, {fetchComments})(Comments);
This could be a way to create Posts component:
I am assuming that when you dispatch fetchPosts() action, you are saving its response using reducers in Redux.
And, you don't need fetchedPosts in local component state as you already have this data in your Redux state.
const Posts = () => {
const posts = useSelector((state) => state.posts)
const dispatch = useDispatch()
// const [fetchedPosts, setFetchedPosts] = useState([]) // NOT needed
useEffect(() => {
dispatch(fetchPosts())
// setFetchedPosts(posts) // NOT needed
// console.log(posts) // NOT needed, its value may confuse you
}, [])
// Do this, if you want to see `posts` in browser log
useEffect(() => {
console.log(posts)
}, [posts])
/* NOT needed
const renderPosts = () => {
posts.map((post) => {
console.log(post)
})
} */
return (
<>
{posts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</>
)
}
export default Posts
I'm making a MERN stack online store website and I'm fetching my products from a useEffect hook in my Shoes.js component. But I'm only getting the initial state from redux instead of the updated state.
The data is being fetched just fine but I can only access the initial state. So the values being passed to the ProductsArea component are false and null How do I get the updated state?
Here's my Shoes.js file:
import React, { useEffect } from 'react';
import './Shoes.css';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { getProducts } from '../../../actions/productsActions';
import ProductsArea from './ProductsArea';
import Navbar from '../landing/Navbar';
import Search from './Search';
export const Shoes = (props) => {
useEffect(() => {
props.getProducts();
console.log(props.products);
console.log(props.loading);
}, []);
if(props.loading) {
return (
<h1>loading</h1>
)
}
else {
return (
<div>
<Navbar />
<div className="shoes">
<Search />
<h1 className="productsTitle">Our Selection</h1>
<ProductsArea loading={props.loading} products={props.products} />
{/* {
props.products.map(product => (
<ProductCard key={product._id} product={product} />
))
} */}
</div>
</div>
)
}
}
const mapStateToProps = state => ({
products: state.products.products,
loading: state.products.loading
})
export default connect(mapStateToProps, { getProducts })(Shoes);
Here's my productsActions file
import {GET_PRODUCTS, SET_LOADING, SET_ERROR} from './types';
export const getProducts = () => async (dispatch) => {
try{
setLoading();
const res = await fetch('http://localhost:5000/products');
const data = await res.json();
console.log(data);
dispatch({
type: GET_PRODUCTS,
payload: data
});
}
catch(err) {
dispatch({
type: SET_ERROR,
payload: err
})
}
}
export const setLoading = () => {
console.log('Loading true');
return {
type: SET_LOADING
}
}
This is the getProductsReducer file:
import {GET_PRODUCTS, SET_LOADING, SET_ERROR} from '../actions/types';
const initialState = {
products: [],
loading: false,
error: null
}
export default (state = initialState, action) => {
switch (action.type) {
case GET_PRODUCTS:
console.log(action.payload);
return {
...state,
products: action.payload,
loading: false
}
case SET_LOADING:
return {
...state,
loading: true
};
case SET_ERROR:
console.log(action.payload);
return {
...state,
error: action.payload
};
default: return state;
}
}
Here's my index.js file for redux :
import {combineReducers} from 'redux';
import getProductReducer from './getProductReducer';
export default combineReducers({
products: getProductReducer
});
And the Store.js file:
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const initialState = {};
const middleware = [thunk];
const store = createStore(rootReducer, initialState, composeWithDevTools(applyMiddleware(...middleware)));
export default store;
So I checked the redux extension and the state is showing up on my Home.js page but not on the Shoes.js file
Here's the Home.js file:
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { getProducts, setLoading } from '../../../actions/productsActions';
import { connect } from 'react-redux';
import {Link} from 'react-router-dom';
import './Home.css';
import Navbar from './Navbar';
export const Home = (props) => {
useEffect(() => {
props.setLoading();
props.getProducts();
//eslint-disable-next-line
console.log(props.products);
console.log(props.loading);
}, []);
if(props.loading) {
return <div>loading</div>
}
else {
return (
<div>
<Navbar />
<div className="home">
<div className="group-1">
<div className="branding">
<div className="brandName">
The
<br/>
Sole
<br/>
Store
</div>
<div>
<p>The finest designs and fits.</p>
</div>
</div>
<div className="viewProducts">
<div>
<p>
Check out our latest and greatest models
</p>
<Link className="productsBtn" to="/shoes">GO <i className="fas fa-arrow-right"/></Link>
</div>
</div>
</div>
<div className="group-2">
<div className="products">
<div className="product"></div>
<div className="product"></div>
<div className="product"></div>
<div className="product"></div>
</div>
<div className="something"></div>
</div>
</div>
</div>
)
}
}
Home.propTypes = {
products: PropTypes.object.isRequired,
loading: PropTypes.bool.isRequired
}
const mapStateToProps = state => ({
products: state.products.products,
loading: state.products.loading
});
export default connect(mapStateToProps, {getProducts, setLoading})(Home);
Although, I'm still only getting the initial state and not the updated state in the console from Home.js too.
I've made the changes that #Kalhan.Toress suggested and this is the updated Shoes.js file
import React, { useEffect } from 'react';
import './Shoes.css';
// import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { getProducts } from '../../../actions/productsActions';
import ProductsArea from './ProductsArea';
import Navbar from '../landing/Navbar';
import Search from './Search';
export const Shoes = (props) => {
useEffect(() => {
props.fetchData();
console.log(JSON.parse(props.products.products));
}, []);
if(props.loading) {
return (
<h1>loading</h1>
)
}
else {
return (
<div>
<Navbar />
<div className="shoes">
<Search />
<h1 className="productsTitle">Our Selection</h1>
<ProductsArea loading={props.loading} products={JSON.parse(props.products.products)} />
{/* {
props.products.map(product => (
<ProductCard key={product._id} product={product} />
))
} */}
</div>
</div>
)
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: () => dispatch(getProducts())
};
};
const mapStateToProps = state => ({
products: state.products.products,
loading: state.products.loading
})
export default connect(mapStateToProps, mapDispatchToProps)(Shoes);
I can click on the link to the Shoes page from Home and everything works perfectly, but as soon as I reload the Shoes.js page or go to it directly, this is the error I get:
Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.
This is my App.js file for the server side where I do have CORS enabled:
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
const productRoute = require('./products/productRoute');
const orderRoute = require('./orders/orderRoute');
const userRoute = require('./users/userRoute');
const adminRoute = require('./admins/adminRoute');
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin','*');
res.header('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Authorization, Accept');
if(res.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, PATCH, DELETE');
}
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use('/products', productRoute);
app.use('/orders', orderRoute);
app.use('/users', userRoute);
app.use('/admin', adminRoute);
app.use((req, res, next) => {
const error = new Error();
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500 ).json({
error: error
})
});
module.exports = app;
I'd really appreciate any help!
Thank you!
I think the way you dispatch the sync action is incorrect
by invoking props.getProducts(); it will return a sync function, that's will not trigger any dispatch action as i see
const getProducts = () => async (dispatch) => {
try{
....
to make sure it put a console.log as below and check it
useEffect(() => {
const returnedFromAction = props.getProducts();
console.log(returnedFromAction); // this should prints the returned function and it will not get dispatched
....
}
Here you need to dispatch a sync action by by executing returning function as below
You have to add a mapDispatchToProps as below
....
const mapDispatchToProps = dispatch => {
return {
fetchData: () => dispatch(getProducts())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);
and then inside the useEffect use this fetchData function to dispatch the fetch action so now in useEffect
useEffect(() => {
props.fetchData();
}, []);
That will do the job for you, i have created a sample demo for you, check it out here
This will align with your approach by not using redux hooks, but theres another way that you can easily do as below.
import { useDispatch } from 'react-redux'; // import the dispatcher
const App = props => {
const dispatch = useDispatch(); // get a reference to dispatch
useEffect(() => {
dispatch(getProducts()); // dispatch the action
}, []);
see it in here
I have been using Redux for a long time, but now decided to try out the new ContextAPI.
I got it working with one component/page (using NextJs), however the state isn't shared between pages/components.
store.js
import React, { createContext, useReducer } from 'react';
import reducer from './reducer'
const initialState = {
players: [],
};
const Store = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<Context.Provider value={[state, dispatch]}>
{children}
</Context.Provider>
)
};
export const Context = createContext(initialState);
export default Store;
reducer.js
const Reducer = (state, action) => {
switch (action.type) {
case 'ADD_PLAYER':
return {
...state,
players: [...state.players, action.payload],
};
case 'REMOVE_PLAYER_BY_INDEX':
const array = state.players;
if (array) {
array.splice(action.payload, 1);
}
return {
...state,
players: !array ? [] : array,
};
default:
return state;
}
};
export default Reducer;
add players page /players/add (addplayerspage.js)
import React, { useContext } from 'react';
import map from 'lodash/map';
import isEqual from 'lodash/isEqual';
import { Context } from '../../../context';
const PlayerCreatePage = () => {
const [_, dispatch] = useContext(Context);
const handleAddPlayer = () => {
dispatch({ type: 'ADD_PLAYER', payload: Math.random() });
};
const handleRemovePlayerByIndex = (index) => {
dispatch({ type: 'REMOVE_PLAYER_BY_INDEX', payload: index });
};
return (
<div className="layout">
<div>
<Context.Consumer>
{([state]) => {
const { players } = state;
return map(players, (p, i) => <div
key={i}
onClick={() => handleRemovePlayerByIndex(i)}
>
{p}
</div>
)
}}
</Context.Consumer>
</div>
<button onClick={() => handleAddPlayer()}>Add new</button>
</div>
);
};
export default React.memo(PlayerCreatePage, (prev, next) => isEqual(prev, next));
lobby players page /players/lobby (lobbyplayerspage.js)
import React, { useContext } from 'react';
import map from 'lodash/map';
import { Context } from '../../../context';
const PlayersLobbyPage = () => {
const [state, _] = useContext(Context);
return (
<div>
<div>
{map(state.players, (p, i) => <div
key={i}
>
{p}
</div>
)}
</div>
</div>
);
};
export default PlayersLobbyPage;
_app.js (NextJs)
import App, { Container } from 'next/app';
import '../styles/main.css';
import Store from '../context';
class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Store>
<Component {...pageProps} />
</Store>
</Container>
);
}
}
export default MyApp;
THE PROBLEM:
Have two tabs open
Add players
Lobby
Add a new player
See that player is added on 'Add players' page
2.See that NOTHING happens on 'Lobby' page
Okay, so the issue is that I was trying to "share" context api state between different open tabs, it doesn't work like that by default, even for redux (tried adding it and faced same result), for redux there's a redux-state-sync library for that, nonetheless I will use sockets in future, so this won't be an issue.
Closed.
I would like ask you about passing object to Redux.
Below is my code.
// src/actions/writingType.js
export const write = () => ({
type: 'WRITE',
})
export const update = (obj) => ({
type: 'UPDATE',
obj
})
// src/reducers/writingType.js
const initialState = {
writingType: "WRITE",
obj: null
}
const writingTypeReducer = (state = initialState, action) => {
console.log('\n inside writingTypeReducer');
console.log(action);
switch (action.type) {
case 'WRITE':
return {
...state,
writingType: 'WRITE'
};
case 'UPDATE':
return {
...state,
writingType: 'UPDATE',
obj: action.obj
};
default:
return state;
}
}
export default writingTypeReducer;
// Contentview.js
import React, { useContext } from 'react';
import { Route, Link } from 'react-router-dom';
import MarkdownRenderer from 'react-markdown-renderer';
import './Contentview.css';
import { connect } from 'react-redux'
import { write, update } from '../../actions/writingType'
import { UserConsumer } from '../../contexts/userContext';
import { Test } from '../../contexts/Test';
const Contentview = (props) => {
/*
category: "React"
contentObj:
contents: "something"
createdDatetime: "2019.10.26 08:52:05"
title: "something"
wikiIndex: 1
*/
console.log('\n Contentview');
console.log(props);
console.log('\n update(props.contentObj);');
update(props.contentObj);
const url = "/editor/" + props.category;
const updateUrl = "/update/" + props.category;
return (
<div>
<div className="categoryDiv">{props.category}</div>
<div className="writingDiv"><Link to={url}> A </Link></div>
<div className="updateDiv"><Link to={updateUrl} > B </Link></div>
<hr />
<MarkdownRenderer markdown={props.contentObj.contents} />
</div>
);
};
// export default Contentview;
const mapStateToProps = (state, props) => ({
writetypestate: state.writingType,
obj: props.contentObj
})
const mapDispatchToProps = dispatch => ({
write: () => dispatch(write()),
update: (obj) => {
console.log('Contentview, mapDispatchToProps, update');
dispatch(update(obj))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Contentview)
I used update(props.contentObj); in Contentview.js to pass props.contentObj to Redux and update obj of initialState in src/reducers/writingType.js. But obj of initialState hasn't changed and existed as null.
How should I change code?
Thank you.
use props.update to call in the main file
// Contentview.js
import React, { useContext } from 'react';
import { Route, Link } from 'react-router-dom';
import MarkdownRenderer from 'react-markdown-renderer';
import './Contentview.css';
import { connect } from 'react-redux'
import { write, update } from '../../actions/writingType'
import { UserConsumer } from '../../contexts/userContext';
import { Test } from '../../contexts/Test';
const Contentview = (props) => {
/*
category: "React"
contentObj:
contents: "something"
createdDatetime: "2019.10.26 08:52:05"
title: "something"
wikiIndex: 1
*/
console.log('\n Contentview');
console.log(props);
console.log('\n update(props.contentObj);');
props.update(props.contentObj);
const url = "/editor/" + props.category;
const updateUrl = "/update/" + props.category;
return (
<div>
<div className="categoryDiv">{props.category}</div>
<div className="writingDiv"><Link to={url}> A </Link></div>
<div className="updateDiv"><Link to={updateUrl} > B </Link></div>
<hr />
<MarkdownRenderer markdown={props.contentObj.contents} />
</div>
);
};
// export default Contentview;
const mapStateToProps = (state, props) => ({
writetypestate: state.writingType,
obj: props.contentObj
})
const mapDispatchToProps = dispatch => ({
write: () => dispatch(write()),
update: (obj) => {
console.log('Contentview, mapDispatchToProps, update');
dispatch(update(obj))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Contentview)
Please use the above code