React/Redux - 将变量传递给动作

Posted

技术标签:

【中文标题】React/Redux - 将变量传递给动作【英文标题】:React/Redux - Pass variable to action 【发布时间】:2019-03-23 19:57:13 【问题描述】:

我是 Redux 的新手,正在使用 Spotify API 进行项目。我正在发送 API 调用并检索有关当前播放歌曲的数据。

我有一个单独的 Redux 操作,它试图从当前播放的艺术家那里获取其他专辑。在我的 App.js 中,我可以通过 const id = this.props.currentlyPlaying.id 访问艺术家的 ID

我想将此变量从 App.js 传递给我的相册操作。该操作包含 API 调用,如下所示:

import SpotifyWebApi from 'spotify-web-api-js';
import id from '../App.js';
const spotifyApi = new SpotifyWebApi();

export function fetchAlbums() 
  return function(dispatch) 
    dispatch( type: "FETCH_ALBUMS_BY_ARTIST");

    //'43ZHCT0cAZBISjO8DG9PnE'
    spotifyApi.getArtistAlbums(id)
      .then((response) => 
        dispatch( type: "FETCH_ALBUMS_BY_ARTIST_FULFILLED", payload: response)
      )
      .catch((err) => 
        dispatch( type: "FETCH_ALBUMS_BY_ARTIST_REJECTED", payload: err)
      );

  

我尝试导入 id 变量,但出现错误。将变量从组件传递到 Redux 操作的正确方法是什么?我也试过通过this.props直接在action中访问id,也不管用。

【问题讨论】:

【参考方案1】:

不要尝试导入 id,在调用fetchAlbums 操作时将其作为参数传递。

类似:

动作:

export const fetchAlbums = (id) => async dispatch => 
  dispatch( type: "FETCH_ALBUMS_BY_ARTIST");

  //'43ZHCT0cAZBISjO8DG9PnE'
  spotifyApi.getArtistAlbums(id)
    .then((response) => 
      dispatch( type: "FETCH_ALBUMS_BY_ARTIST_FULFILLED", payload: response)
    )
    .catch((err) => 
      dispatch( type: "FETCH_ALBUMS_BY_ARTIST_REJECTED", payload: err)
    );

使用行动:

这将绑定一个函数来调用fetchAlbums 函数,允许您传递参数而不是click 事件。

<button onClick=() => fetchAlbums(id)>Fetch Album</button>

【讨论】:

【参考方案2】:

您需要做的是,当您从组件调用操作时,将 th id 传递给操作函数。像这样: 我还会推荐你使用 redux-thunk 中间件来处理异步操作。

export function fetchAlbums(id) 
  return function(dispatch,id) 
    dispatch( type: "FETCH_ALBUMS_BY_ARTIST");

    //'43ZHCT0cAZBISjO8DG9PnE'
    spotifyApi.getArtistAlbums(id)
      .then((response) => 
        dispatch( type: "FETCH_ALBUMS_BY_ARTIST_FULFILLED", payload: response)
      )
      .catch((err) => 
        dispatch( type: "FETCH_ALBUMS_BY_ARTIST_REJECTED", payload: err)
      );

  

【讨论】:

【参考方案3】:

我的配置:

    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",

我们可以像这样将值传递给调度函数,

切片文件

import  createSlice  from '@reduxjs/toolkit'

export const rootSlice = createSlice(
    name: 'root',
    initialState: 
        posts: [
             id: 1, title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" ,
             id: 2, title: "qui est esse", body: "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" ,
             id: 3, title: "ea molestias quasi exercitationem repellat qui ipsa sit aut", body: "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut" ,
        ],
    ,
    reducers: 
        deletePost: (state, action) => 
            console.log("state: " + state.posts)
            console.log("action: " + action.payload.id)
            console.log("action: " + action.payload.extra_val)
            // to do
            let newPost = state.posts.filter(post => 
                return action.payload.id !== post.id
            )
            return 
                ...state,
                posts: newPost
            
        ,
    ,
)

// Action creators are generated for each case reducer function
export const  deletePost  = rootSlice.actions

export default rootSlice.reducer

发布文件

import React from 'react';
import  useParams, useNavigate  from 'react-router-dom';
import  useSelector, useDispatch  from 'react-redux'
import  deletePost  from '../reducers/rootSlice'

const Post = () => 
    let navigate = useNavigate();
    let  post_id  = useParams();
    const posts = useSelector((state) => state.root.posts);
    var singPost = (id) => posts.find(obj => obj.id === parseInt(id))
    const dispatch = useDispatch()

    const handleClick = (id) => 
        dispatch(deletePost( id, extra_val: 'ok-1' ));
        navigate("/");
    

    const post = (id) => 
        var sp = singPost(id);
        return sp ? (
            <div className="post">
                <h4 className="center">sp.title</h4>
                <p>sp.body</p>
                <button onClick=() => handleClick(sp.id)>deletePost</button>
            </div>
        ) : (
            <div className="center">Loading posts...</div>
        );
    
    return (
        <div className="container">
            post(post_id)
        </div>
    );


export default Post;

参考:

https://react-redux.js.org/tutorials/quick-start https://react-redux.js.org/using-react-redux/connect-mapdispatch https://reactrouter.com/docs/en/v6/getting-started/concepts#navigate-function

【讨论】:

以上是关于React/Redux - 将变量传递给动作的主要内容,如果未能解决你的问题,请参考以下文章

React/Redux 在第一个动作完成后立即触发动作

react+redux 中如何通过请求动作处理中间件并触发成功动作?

React-Redux:在 React 组件中使用动作创建器

React Redux:动作创建者不调用reducer

另一个组件如何在 react/redux 中监听另一个组件的动作?

reducer.state.props 在嵌套动作 react/redux 中未定义