Redux:状态更新后组件未更新

时间:2021-06-03 18:50:01

标签: javascript reactjs redux ecmascript-6

我已经创建了 reducer 并使用它来更改我的商店的状态。但是正如您在 App.js 中看到的那样,每当我单击按钮并更新状态时。它更新。我可以在控制台中看到它。但组件不更新。正如你所看到的,我有曲目列表,它没有更新。如果我因为组件重新渲染而对代码进行任何更改,我可以在此之后看到新状态。为什么状态更新时不自动渲染。

行动

import * as actions from './actionTypes'

export const trackAdded = (title, artist, audioSrc, img) => {
    return {
        type: actions.TRACK_ADDED,
        payload: {
            title,
            artist,
            audioSrc,
            img
        }
    }
}

减速器

import * as actions from './actionTypes'

export default function reducer(state = [], action) {
    switch (action.type) {
        case actions.TRACK_ADDED:
            return [
                ...state,
                {
                    title: action.payload.title,
                    artist: action.payload.artist,
                    audioSrc: action.payload.audioSrc,
                    img: action.payload.img
                }
            ]

        default:
            return state
    }
}

App.js

import './App.css';
import store from './store'
import { trackAdded } from './actions'

function App() {
  const add = (title) => {
    store.dispatch(trackAdded(title, "Taylor Swift", "src", "image"))
    console.log(store.getState())
  }
  
  return (
    <div className="App">
      {store.getState().map((track, track_id) => {
        return (
          <li key={track_id}>{track.title}</li>
        )
      })}
      <button onClick={() => { add("Shake It Off") }}>Add Track</button>

    </div>
  );
}

export default App;

2 个答案:

答案 0 :(得分:1)

组件不会更新,因为 store.getState() 中的 <div className="App"> 只会在组件被调用时运行一次。不存在告诉组件重新运行 store.getState() 的逻辑。如果您希望组件在商店状态更改时接收更新,则需要使用 react-reduxconnect 函数或 useSelector 挂钩将其连接到商店。

例如,如果使用 connect 函数,您可以将 redux 状态映射到 react 组件的 props。因此,如果组件的 props 发生变化,则该组件将对它的 props 发生“反应”。 redux 状态到组件 props 的映射发生在 mapStateToProps 函数中,返回一个映射到组件的 prop tracks。否则组件没有理由更新。另请注意:在下面的示例中,商店通过 Provider 组件连接到 React,将商店提供给希望连接到它的子组件。

import { Provider, connect } from 'react-redux'

import './App.css';
import store from './store'
import { trackAdded } from './actions'

function App(props) {
  const add = (title) => {
    store.dispatch(trackAdded(title, "Taylor Swift", "src", "image"))
    console.log(store.getState())
  }
  
  return (
    <Provider store={store}>
      <div className="App">
        {props.tracks.map((track, track_id) => {
          return (
            <li key={track_id}>{track.title}</li>
          )
        })}
        <button onClick={() => { add("Shake It Off") }}>Add Track</button>
      </div>
    </Provider>
  );
}

const mapStateToProps = (state) => {
  const tracks = state
  return { tracks }
}

export default connect(mapStateToProps)(App);

话虽如此,如果您走 connect 路线,您可能希望向 mapDispatchToProps 添加一个 connect 函数,这样您就不会到处传递 store。您可以在 redux 文档中找到该信息,但这将是另一个问题的答案。

答案 1 :(得分:-1)

发生这种情况是因为您的组件不知道商店已更新,您可以使用类似这样的东西

Range: (-2, 2)
Starting value in the range: 1
Added value: 14

min = -2
max = 2
starting position = 1
added value = 14

cycle = 2 * (max - min) = 2 * 4 = 8

full cycles = round_toward_zero(added value / cycle)
            = round_toward_zero(14 / 8)
            = round_toward_zero(1.75)
            = 1

modified value = added value - cycle * full cycles
               = 14 - 8 * 1
               = 6

position = starting position + modified value
         = 1 + 6
         = 7

position = 7 > 2 = max

position' = max - (position - max)
          = 2 - (7 - 2)
          = 2 - 5
          = -3

position' = -3 < -2 = min

position'' = min + (min - position')
           = -2 + (-2 - -3)
           = -2 + 1
           = -1

但这绝对不推荐。您可能希望使用 react-redux 中的 useEffect(() => { this.artistList = store.getState(); }, [store.getState()]); // kind of watcher of store.getState() ,这是一种非常简洁且推荐的方法。