Tôi có thể gửi một hành động trong giảm tốc?


196

Có thể gửi một hành động trong một bộ giảm tốc? Tôi có một thanh tiến trình và một yếu tố âm thanh. Mục tiêu là cập nhật thanh tiến trình khi thời gian được cập nhật trong phần tử âm thanh. Nhưng tôi không biết nơi đặt trình tạo sự kiện ontimeupdate hoặc cách gửi một hành động trong cuộc gọi lại của ontimeupdate, để cập nhật thanh tiến trình. Đây là mã của tôi:

//reducer

const initialState = {
    audioElement: new AudioElement('test.mp3'),
    progress: 0.0
}

initialState.audioElement.audio.ontimeupdate = () => {
    console.log('progress', initialState.audioElement.currentTime/initialState.audioElement.duration);
    //how to dispatch 'SET_PROGRESS_VALUE' now?
};


const audio = (state=initialState, action) => {
    switch(action.type){
        case 'SET_PROGRESS_VALUE':
            return Object.assign({}, state, {progress: action.progress});
        default: return state;
    }

}

export default audio;

AudioElementgì Có vẻ như đó không phải là một cái gì đó trong trạng thái.
ebuat3989

nó là một lớp đơn giản ES6 (không có phản ứng), giữ một Đối tượng âm thanh. Nếu nó không ở trong trạng thái, làm thế nào tôi kiểm soát chơi / dừng, bỏ qua, v.v.?
klanm

2
Bạn có thể muốn xem xét redux saga
Kyeotic

Câu trả lời:


150

Gửi một hành động trong một bộ giảm tốc là một mô hình chống . Bộ giảm tốc của bạn nên không có tác dụng phụ, chỉ cần tiêu hóa tải trọng hành động và trả về một đối tượng trạng thái mới. Thêm người nghe và gửi các hành động trong bộ giảm tốc có thể dẫn đến các hành động bị xiềng xích và các tác dụng phụ khác.

Âm thanh như AudioElementlớp khởi tạo của bạn và người nghe sự kiện thuộc về một thành phần chứ không phải ở trạng thái. Trong trình lắng nghe sự kiện, bạn có thể gửi một hành động, sẽ cập nhậtprogress trạng thái.

Bạn có thể khởi tạo AudioElementđối tượng lớp trong thành phần React mới hoặc chỉ chuyển đổi lớp đó thành thành phần React.

class MyAudioPlayer extends React.Component {
  constructor(props) {
    super(props);

    this.player = new AudioElement('test.mp3');

    this.player.audio.ontimeupdate = this.updateProgress;
  }

  updateProgress () {
    // Dispatch action to reducer with updated progress.
    // You might want to actually send the current time and do the
    // calculation from within the reducer.
    this.props.updateProgressAction();
  }

  render () {
    // Render the audio player controls, progress bar, whatever else
    return <p>Progress: {this.props.progress}</p>;
  }
}

class MyContainer extends React.Component {
   render() {
     return <MyAudioPlayer updateProgress={this.props.updateProgress} />
   }
}

function mapStateToProps (state) { return {}; }

return connect(mapStateToProps, {
  updateProgressAction
})(MyContainer);

Lưu ý rằng updateProgressActiongói được tự động đóng gói dispatchđể bạn không cần gọi công văn trực tiếp.


cảm ơn bạn rất nhiều vì đã làm rõ Nhưng tôi vẫn không biết cách truy cập người điều phối. Tôi luôn luôn sử dụng phương thức kết nối từ Reac-redux. nhưng tôi không biết làm thế nào để gọi nó trong phương thức updateProTHER. Hoặc có một cách khác để có được người điều phối. có thể với đạo cụ? cảm ơn bạn
klanm

Không vấn đề gì. Bạn có thể chuyển hành động đến MyAudioPlayerthành phần từ thùng chứa cha có connected react-redux. Kiểm tra cách thực hiện điều đó mapDispatchToPropstại đây: github.com/reactjs/react-redux/blob/master/docs/
Kẻ

6
Đâu là biểu tượng updateProgressActionđược định nghĩa trong ví dụ của bạn?
Charles Prakash Dasari

2
Nếu bạn không được yêu cầu gửi một hành động trong một bộ giảm tốc, thì liệu redux-thunk có phá vỡ các quy tắc của redux không?
Eric Wiener

2
@EricWiener Tôi tin rằng redux-thunkđang gửi một hành động từ một hành động khác, không phải là bộ giảm tốc. stackoverflow.com/questions/35411423/
hy

159

Bắt đầu một công văn khác trước khi bộ giảm tốc của bạn kết thúc là một mẫu chống , bởi vì trạng thái bạn nhận được khi bắt đầu bộ giảm tốc sẽ không còn là trạng thái ứng dụng hiện tại nữa khi bộ giảm tốc của bạn kết thúc. Nhưng lên lịch một công văn khác từ bên trong bộ giảm tốc KHÔNG phải là một mô hình chống . Trên thực tế, đó là những gì ngôn ngữ Elm làm và như bạn biết Redux là một nỗ lực để đưa kiến ​​trúc Elm vào JavaScript.

Đây là một phần mềm trung gian sẽ thêm tài sản asyncDispatchcho tất cả các hành động của bạn. Khi trình giảm tốc của bạn kết thúc và trả về trạng thái ứng dụng mới, asyncDispatchsẽ kích hoạt store.dispatchbất kỳ hành động nào bạn đưa ra cho nó.

// This middleware will just add the property "async dispatch"
// to actions with the "async" propperty set to true
const asyncDispatchMiddleware = store => next => action => {
  let syncActivityFinished = false;
  let actionQueue = [];

  function flushQueue() {
    actionQueue.forEach(a => store.dispatch(a)); // flush queue
    actionQueue = [];
  }

  function asyncDispatch(asyncAction) {
    actionQueue = actionQueue.concat([asyncAction]);

    if (syncActivityFinished) {
      flushQueue();
    }
  }

  const actionWithAsyncDispatch =
    Object.assign({}, action, { asyncDispatch });

  const res = next(actionWithAsyncDispatch);

  syncActivityFinished = true;
  flushQueue();

  return res;
};

Bây giờ bộ giảm tốc của bạn có thể làm điều này:

function reducer(state, action) {
  switch (action.type) {
    case "fetch-start":
      fetch('wwww.example.com')
        .then(r => r.json())
        .then(r => action.asyncDispatch({ type: "fetch-response", value: r }))
      return state;

    case "fetch-response":
      return Object.assign({}, state, { whatever: action.value });;
  }
}

7
Marcelo, bài đăng trên blog của bạn ở đây thực hiện một công việc tuyệt vời mô tả hoàn cảnh tiếp cận của bạn, vì vậy tôi đang liên kết với nó ở đây: lazamar.github.io/dispatching-from-inside-of-reducers
Dejay Clayton

3
Đây chính xác là những gì tôi cần, ngoại trừ phần mềm trung gian như đang phá vỡ dispatchsẽ trả lại hành động. Tôi đã thay đổi các dòng cuối cùng thành: const res = next(actionWithAsyncDispatch); syncActivityFinished = true; flushQueue(); return res;và nó hoạt động rất tốt.
zanerock

1
Nếu bạn không được yêu cầu gửi một hành động trong một bộ giảm tốc, thì liệu redux-thunk có phá vỡ các quy tắc của redux không?
Eric Wiener

Làm thế nào điều này hoạt động khi bạn cố gắng xử lý các phản hồi websocket? Đây là mặc định xuất giảm tốc của tôi (trạng thái, hành động) => {const m2 = [... state.messages, action.payload] return Object.assign ({}, state, {message: m2,})} và TÔI VẪN nhận được lỗi này "đột biến trạng thái được phát hiện ở giữa các công văn"
quantumpotato

12

Bạn có thể thử sử dụng một thư viện như redux-saga . Nó cho phép một cách rất rõ ràng để sắp xếp các chức năng không đồng bộ, tắt các hành động, sử dụng độ trễ và hơn thế nữa. Nó rất mạnh mẽ!


1
bạn có thể chỉ định làm thế nào để đạt được "lập lịch gửi công văn khác trong bộ giảm tốc" với redux-saga không?
XPD

1
@XPD bạn có thể giải thích thêm một chút về những gì bạn muốn thực hiện không? Nếu bạn đang cố gắng sử dụng một hành động giảm tốc để gửi một hành động khác, bạn sẽ không thể có điều gì đó giống với redux-saga.
chandlervdw

1
Ví dụ: giả sử bạn có một cửa hàng vật phẩm nơi bạn đã tải một phần của các mặt hàng. Các mặt hàng được tải một cách lười biếng. Giả sử một mặt hàng có một nhà cung cấp. Các nhà cung cấp cũng tải một cách lười biếng. Vì vậy, trong trường hợp này có thể có một mặt hàng mà nhà cung cấp của nó đã không được tải. Trong một bộ giảm tốc vật phẩm, nếu chúng ta cần lấy thông tin về một vật phẩm chưa được tải, chúng ta phải tải lại dữ liệu từ máy chủ thông qua một bộ giảm tốc. Trong trường hợp đó, redux-saga giúp gì trong bộ giảm tốc?
XPD

1
Ok, giả sử bạn muốn loại bỏ yêu cầu này để supplierbiết thông tin khi người dùng cố gắng truy cập itemtrang chi tiết. Bạn componentDidMount()sẽ bắn ra một chức năng gửi một hành động, nói FETCH_SUPPLIER. Trong bộ giảm tốc, bạn có thể đánh dấu vào thứ gì đó như loading: trueđể hiển thị một vòng quay trong khi yêu cầu được thực hiện. redux-sagasẽ lắng nghe hành động đó và đáp lại yêu cầu thực tế. Sử dụng các chức năng của trình tạo, sau đó nó có thể đợi phản hồi và đổ nó vào FETCH_SUPPLIER_SUCCEEDED. Bộ giảm tốc sau đó cập nhật các cửa hàng với thông tin nhà cung cấp.
chandlervdw

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.