วิธีรับการจัดส่งอย่างง่ายจาก this.props โดยใช้ connect w / Redux


107

ฉันมีองค์ประกอบ React ง่ายๆที่ฉันเชื่อมต่อ (การแมปอาร์เรย์ / สถานะอย่างง่ายทับ) เพื่อไม่ให้อ้างอิงบริบทของร้านค้าฉันต้องการวิธี "จัดส่ง" โดยตรงจากอุปกรณ์ประกอบฉาก ฉันเคยเห็นคนอื่นใช้แนวทางนี้ แต่ไม่สามารถเข้าถึงได้ด้วยเหตุผลบางประการ :)

นี่คือเวอร์ชันของการพึ่งพา npm แต่ละรายการที่ฉันใช้อยู่ในปัจจุบัน

"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"

นี่คือส่วนประกอบที่มีวิธีการเชื่อมต่อ

class Users extends React.Component {
    render() {
        const { people } = this.props;
        return (
            <div>
                <div>{this.props.children}</div>
                <button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
            </div>
        );
    }
};

function mapStateToProps(state) {
    return { people: state.people };
}

export default connect(mapStateToProps, {
    fetchUsers
})(Users);

หากคุณต้องการเห็นตัวลด (ไม่มีอะไรน่าตื่นเต้น แต่อยู่ที่นี่)

const initialState = {
    people: []
};

export default function(state=initialState, action) {
    if (action.type === ActionTypes.ADD_USER) {
        let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
        return {people: newPeople};
    }
    return state;
};

หากคุณต้องการดูว่าเราเตอร์ของฉันได้รับการกำหนดค่าอย่างไร w / redux

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

var Route = (
  <Provider store={store}>
    <Router history={createBrowserHistory()}>
      {Routes}
    </Router>
  </Provider>
);

อัพเดต

ดูเหมือนว่าถ้าฉันละเว้นการจัดส่งของตัวเองในการเชื่อมต่อ (ขณะนี้อยู่ด้านบนฉันกำลังแสดง fetchUsers) ฉันจะได้รับการจัดส่งฟรี (เพียงไม่แน่ใจว่าปกติแล้วการตั้งค่าที่มีการกระทำแบบ async จะทำงานอย่างไร) คนมิกซ์แอนด์แมตช์กันหมดหรือเปล่า?

[mapDispatchToProps]

คำตอบ:


280

โดยค่าเริ่มต้นเป็นเพียงmapDispatchToProps ดังนั้นหากคุณไม่ระบุอาร์กิวเมนต์ที่สองให้คุณจะได้รับการฉีดเข้าไปในส่วนประกอบของคุณdispatch => ({ dispatch })
connect()dispatch

หากคุณส่งผ่านฟังก์ชันที่กำหนดเองไปmapDispatchToPropsคุณสามารถทำอะไรก็ได้กับฟังก์ชันนี้
ตัวอย่างบางส่วน:

// inject onClick
function mapDispatchToProps(dispatch) {
  return {
    onClick: () => dispatch(increment())
  };
}

// inject onClick *and* dispatch
function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(increment())
  };
}

เพื่อช่วยคุณประหยัดการพิมพ์ Redux bindActionCreators()ที่ช่วยให้คุณสามารถทำได้:

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

ในสิ่งนี้:

import { bindActionCreators } from 'redux';

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

หรือสั้นกว่านั้นเมื่อชื่อเสาตรงกับชื่อผู้สร้างการกระทำ:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

หากคุณต้องการคุณสามารถเพิ่มได้dispatchด้วยมือ:

// injects increment, decrement, and dispatch itself
function mapDispatchToProps(dispatch) {
  return {
    ...bindActionCreators({ increment, decrement }), // es7 spread syntax
    dispatch
  };
}

ไม่มีคำแนะนำอย่างเป็นทางการว่าคุณควรทำสิ่งนี้หรือไม่ connect()โดยปกติจะทำหน้าที่เป็นขอบเขตระหว่างส่วนประกอบ Redux-Aware และ Redux-unaware นี่คือเหตุผลที่เรามักจะรู้สึกว่ามันไม่ได้ทำให้ความรู้สึกที่จะฉีดทั้งdispatchผู้สร้างและการดำเนินการที่ถูกผูกไว้ แต่ถ้าคุณรู้สึกว่าจำเป็นต้องทำสิ่งนี้อย่าลังเลที่จะทำ

bindActionCreatorsสุดท้ายรูปแบบที่คุณกำลังใช้อยู่ในขณะนี้เป็นทางลัดที่จะยิ่งสั้นกว่าโทร เมื่อสิ่งที่คุณทำคือกลับมาbindActionCreatorsคุณสามารถละเว้นการโทรได้แทนที่จะทำสิ่งนี้:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

สามารถเขียนได้ตามนี้

export default connect(
  mapStateToProps,
  { increment, decrement } // injects increment and decrement
)(App);

อย่างไรก็ตามคุณจะต้องละทิ้งไวยากรณ์สั้น ๆ ที่ดีเมื่อใดก็ตามที่คุณต้องการบางอย่างที่กำหนดเองมากขึ้นเช่นการส่งผ่านdispatchเช่นกัน


2
@DanAbramov btw เป็นพารามิเตอร์ที่สองในbindActionCreators(actionCreators, dispatch)ตัวเลือกหรือไม่ ฉันสังเกตเห็นในรหัสของคุณที่// es7 spread syntaxบรรทัดdispatchจะไม่ถูกส่งไปยังbindActionCreators
yonasstephen

วิธีการเพิ่มภายในคืออะไร?
Khurshid Ansari

ไวยากรณ์การแพร่กระจายของ es7 ควรเป็น function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ increment, decrement }), dispatch }; }
Black

6

โดยปกติคุณสามารถผสมและจับคู่ตามสิ่งที่คุณต้องการ

คุณสามารถส่งdispatchต่อเป็นเสาได้หากนั่นคือสิ่งที่คุณต้องการ:

export default connect(mapStateToProps, (dispatch) => ({
    ...bindActionCreators({fetchUsers}, dispatch), dispatch
}))(Users);

ฉันไม่แน่ใจว่าfetchUsersใช้อย่างไร (เป็นฟังก์ชัน async หรือไม่) แต่โดยปกติคุณจะใช้บางอย่างเช่นbindActionCreatorsการเชื่อมโยงการจัดส่งอัตโนมัติจากนั้นคุณจะไม่ต้องกังวลกับการใช้งานdispatchโดยตรงในส่วนประกอบที่เชื่อมต่อ

การใช้การdispatchเรียงลำดับไดเร็กทอรีของคู่กับองค์ประกอบที่ไร้สถานะที่เป็นใบ้กับ redux ซึ่งสามารถทำให้พกพาได้น้อยลง


3
สิ่งที่คุณแนะนำจะไม่ได้ผล คุณจะได้รับการfetchUsersฉีดที่ไม่ถูกผูกไว้เป็นเสา สัญกรณ์ทางลัดจะใช้งานได้ก็ต่อเมื่อคุณส่งผ่านวัตถุเป็นอาร์กิวเมนต์ที่สอง เมื่อคุณผ่านฟังก์ชั่นคุณต้องเรียกbindActionCreatorsตัวเองว่า: dispatch => ({ ...bindActionCreators({ fetchUsers }, dispatch), dispatch }).
Dan Abramov

เหตุใดจึงแพร่กระจายและส่งผ่านในการจัดส่งโดยตรงใน bindActionCreators? dispatch => ( bindActionCreators({ dispatch, fetchUsers }, dispatch))
user3711421

2

ในขณะที่คุณสามารถผ่านdispatchเป็นส่วนหนึ่งได้dispatchToPropsฉันขอแนะนำให้หลีกเลี่ยงการเข้าถึงstoreหรือdispatchโดยตรงจากภายในส่วนประกอบของคุณ ดูเหมือนว่าคุณจะได้รับการบริการที่ดีกว่าโดยส่งผ่านผู้สร้างการกระทำที่ถูกผูกไว้ในอาร์กิวเมนต์ที่ 2 ของ ConnectdispatchToProps

ดูตัวอย่างที่ฉันโพสต์ที่นี่https://stackoverflow.com/a/34455431/2644281เกี่ยวกับวิธีส่งต่อ "ผู้สร้างการกระทำที่ถูกผูกไว้แล้ว" ด้วยวิธีนี้ส่วนประกอบของคุณไม่จำเป็นต้องรู้โดยตรงหรือขึ้นอยู่กับร้านค้า / การจัดส่ง .

ขออภัยที่พูดสั้น ๆ ฉันจะอัปเดตด้วยข้อมูลเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.