簡體   English   中英

為什么我的組件在 state 更改時不重新呈現 (redux)?

[英]Why doesn't my component re-render when state changes (redux)?

我正在學習 redux 並且我正在制作一種 pokedex 應用程序,我一次從 pokeapi.co 獲取 20 個口袋妖怪。 當頁面更改時,會獲取一個包含 20 個 pokemon 的新列表。 問題是,雖然 state 更改為新的口袋妖怪,但它們實際上並沒有呈現。

應用程序.js

const App = () => {
  const dispatch = useDispatch();
  const offset = useSelector(state => state.offset);
  const limit = useSelector(state => state.limit);

  useEffect(() => {
    //FETCHES 20 OBJECTS THAT CONTAIN AN URL TO AN INDIVIDUAL POKEMON
    dispatch(fetchPokemons(limit, offset));
  }, [limit, offset, dispatch]);

...

return (
    <div style={{ backgroundColor: '#222222' }}>
      <Notification />
      <AppBarPokemon />
      <Switch>
        <Route path="/pokemons">
          <PokemonsDisplay CapsFirstLetter={CapsFirstLetter}/>
        </Route>
...

PokemonsDisplay.js

const PokemonsDisplay = ({ CapsFirstLetter }) => {
    const dispatch = useDispatch();
    const classes = useStyles();
    const pokemons = useSelector(state => state.pokemons);
    console.log(pokemons);
    const pageSize = 20;
    const totalCount = 898;

    const handleClick = (p) => {
        dispatch(getOnePokemon(p));
    };

    return (
        <div className={classes.root}>
                {pokemons && (
                    <Grid container spacing={3}>
                        {pokemons.map(p => (
                    <Grid item xs={3} key={p.name} className={classes.gridItem} component={Link} onClick={() => handleClick(p)} to={`/pokemons/${p.name}`} data-cy={`pokemon-button-${p.name}`}>
                            <Paper className={classes.paper && classes.color} elevation={10}>
                                <p className={classes.p}>#{p.id}</p>
                                <p className={classes.p}>{CapsFirstLetter(p.name)}</p>
                                {p.sprites.other["dream_world"]["front_default"] !== null ? 
                                <img className={classes.image} alt={`${p.name}'s sprite`} src={p.sprites.other["dream_world"]["front_default"]}/> : 
                                <img className={classes.image} alt={`${p.name}'s sprite`} src={p.sprites.other["official-artwork"]["front_default"]}/>}
                            </Paper>
                    </Grid>
                ))}
                    </Grid>
                )}
            <Pagination
                totalCount={totalCount} 
                pageSize={pageSize}
            />
        </div>
    );
};

精靈寶可夢Reducer.js

import getPokemons from '../services/pokemons';
import axios from 'axios';
import { loadPokemonsFromLS, savePokemonsList } from '../utils/localStoragePokemons';

const pokemonsReducer = (state = [], action) => {
    console.log('state is:', state)
    switch(action.type){
        case 'INIT_POKEMONS':
            return action.data;
        default:
            return state;
    };
};

export const fetchPokemons = (limit, offset) => {
    return async dispatch => {
        try {
            const pokemons = loadPokemonsFromLS(limit, offset);
            dispatch({
                type: 'INIT_POKEMONS',
                data: pokemons
            });
        } catch (error) {
            const pokemons = await getPokemons.getPokemons(limit, offset);
            let pokemonsArray = [];
            let pokemonsObject = {};
            pokemons.results.forEach(async (r, i) => {
                //FETCHES EACH POKEMON URL AND STORES ITS DATA ON pokemons STATE
                const pokemonNow = await axios.get(r.url);
                pokemonsArray.push(pokemonNow.data);
                pokemonsObject[i] = pokemonNow.data
            });
            savePokemonsList(limit, offset, pokemonsObject);
            dispatch({
                type: 'INIT_POKEMONS',
                data: pokemonsArray
            });
        }
    };
};

export default pokemonsReducer;

我試過dispatch({ data: [...pokemons] })但它不起作用。

我也忘了補充。 當我將 go 發送到路由到“/”然后返回到“/pokemons”的組件時,它們會呈現。

編輯:我想我到了那里。

我更改了 reducer function 以便它獨立於調度被調用,問題是現在動作不會被解雇 xD。

export const fetchEverything = async (limit, offset) => {
    try {
        const pokemons = loadPokemonsFromLS(limit, offset);
        initPokemons(pokemons);
    } catch (error) {
        const pokemonsData = await getPokemons.getPokemons(limit, offset);
        let pokemons = [];
        let pokemonsObject = {};
        console.log(pokemonsData)
        pokemonsData.results.forEach(async (r, i) => {
            //FETCHES EACH POKEMON URL AND STORES ITS DATA ON pokemons STATE
            const pokemonNow = await axios.get(r.url);
            pokemonsObject[i] = pokemonNow.data;
            //console.log([pokemonNow.data][0]);
            pokemons.push(pokemonNow.data);
        });
        console.log(pokemons);
        console.log(pokemonsObject);
        savePokemonsList(limit, offset, pokemonsObject);
        initPokemons(pokemons);
    };
};

export const initPokemons = (pokemons) => {
    return dispatch => dispatch({ type: 'INIT_POKEMONS', pokemons: pokemons })
};

const pokemonsReducer = (state = [], action) => {
    switch(action.type){
        case 'INIT_POKEMONS':
            console.log(action);
            const newState = action.pokemons
            return newState;
        default:
            return state;
    };
};

它是由於 redux state 突變而發生的,您也可以使用 immer 解決此問題,如 redux 文檔中所述。
https://www.npmjs.com/package/immer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM