มีหลายวิธีในการสื่อสารส่วนประกอบ บางคนสามารถเหมาะกับกรณีของคุณ นี่คือรายการของบางอย่างที่ฉันพบว่ามีประโยชน์ที่จะรู้
เกิดปฏิกิริยา
การสื่อสารโดยตรงของผู้ปกครอง / เด็ก
const Child = ({fromChildToParentCallback}) => (
<div onClick={() => fromChildToParentCallback(42)}>
Click me
</div>
);
class Parent extends React.Component {
receiveChildValue = (value) => {
console.log("Parent received value from child: " + value); // value is 42
};
render() {
return (
<Child fromChildToParentCallback={this.receiveChildValue}/>
)
}
}
ที่นี่องค์ประกอบย่อยจะเรียกการเรียกกลับที่ผู้ปกครองให้ไว้พร้อมกับค่าและผู้ปกครองจะสามารถรับค่าที่เด็กได้รับจากผู้ปกครองได้
หากคุณสร้างคุณสมบัติ / หน้าของแอปของคุณจะดีกว่าถ้ามีผู้ปกครองคนเดียวที่จัดการ callbacks / state ( container
หรือที่เรียกว่าหรือsmart component
) และ childs ทั้งหมดจะไร้สัญชาติเพียง แต่รายงานสิ่งต่าง ๆ ให้กับผู้ปกครอง วิธีนี้คุณสามารถ "แบ่งปัน" สถานะของผู้ปกครองกับเด็ก ๆ ที่ต้องการได้อย่างง่ายดาย
บริบท
บริบทการตอบสนองอนุญาตให้เก็บสถานะไว้ที่รากของลำดับชั้นส่วนประกอบของคุณและสามารถฉีดสถานะนี้ได้อย่างง่ายดายเป็นส่วนประกอบซ้อนกันลึกมากโดยไม่ต้องยุ่งยากที่จะต้องส่งอุปกรณ์ประกอบฉากไปยังทุกองค์ประกอบระดับกลาง
ก่อนหน้านี้บริบทเป็นคุณลักษณะทดลอง แต่ API ใหม่มีให้บริการใน React 16.3
const AppContext = React.createContext(null)
class App extends React.Component {
render() {
return (
<AppContext.Provider value={{language: "en",userId: 42}}>
<div>
...
<SomeDeeplyNestedComponent/>
...
</div>
</AppContext.Provider>
)
}
};
const SomeDeeplyNestedComponent = () => (
<AppContext.Consumer>
{({language}) => <div>App language is currently {language}</div>}
</AppContext.Consumer>
);
ผู้บริโภคใช้รูปแบบฟังก์ชันการแสดงผล prop / children
ตรวจสอบโพสต์บล็อกนี้สำหรับรายละเอียดเพิ่มเติม
ก่อนที่จะตอบสนอง 16.3 ฉันขอแนะนำให้ใช้react-broadcastซึ่งมี API ที่ค่อนข้างคล้ายกันและใช้ API บริบทเดิม
พอร์ทัล
ใช้พอร์ทัลเมื่อคุณต้องการให้ส่วนประกอบทั้ง 2 อยู่ติดกันเพื่อทำให้พวกมันสื่อสารกับฟังก์ชั่นง่าย ๆ เช่นในแม่ / ลูกปกติ แต่คุณไม่ต้องการให้ 2 ส่วนประกอบเหล่านี้มีความสัมพันธ์แบบพ่อแม่ / ลูกใน DOM เพราะ ของข้อ จำกัด ของ visual / CSS ที่แสดงถึง (เช่น z-index, opacity ... )
ในกรณีนี้คุณสามารถใช้ "พอร์ทัล" มีไลบรารีการตอบสนองที่แตกต่างกันโดยใช้พอร์ทัลซึ่งโดยปกติจะใช้สำหรับmodal , popups, tooltips ...
พิจารณาสิ่งต่อไปนี้:
<div className="a">
a content
<Portal target="body">
<div className="b">
b content
</div>
</Portal>
</div>
สามารถสร้าง DOM ต่อไปนี้เมื่อแสดงผลภายในreactAppContainer
:
<body>
<div id="reactAppContainer">
<div className="a">
a content
</div>
</div>
<div className="b">
b content
</div>
</body>
รายละเอียดเพิ่มเติมที่นี่
สล็อต
คุณกำหนดช่องที่ใดที่หนึ่งแล้วเติมช่องจากสถานที่อื่นของโครงสร้างการแสดงผลของคุณ
import { Slot, Fill } from 'react-slot-fill';
const Toolbar = (props) =>
<div>
<Slot name="ToolbarContent" />
</div>
export default Toolbar;
export const FillToolbar = ({children}) =>
<Fill name="ToolbarContent">
{children}
</Fill>
สิ่งนี้คล้ายกับพอร์ทัลยกเว้นเนื้อหาที่กรอกจะถูกเรนเดอร์ในสล็อตที่คุณกำหนดในขณะที่พอร์ทัลโดยทั่วไปจะแสดงโหนด dom ใหม่ (มักเป็นลูกของ document.body)
ตรวจสอบไลบรารีการเติมช่องเสียบ
รถบัสกิจกรรม
ตามที่ระบุในเอกสารตอบโต้:
สำหรับการสื่อสารระหว่างสององค์ประกอบที่ไม่มีความสัมพันธ์แบบพ่อแม่ลูกคุณสามารถตั้งค่าระบบเหตุการณ์ส่วนกลางของคุณเอง สมัครสมาชิกกิจกรรมใน componentDidMount () ยกเลิกการสมัครสมาชิก componentWillUnmount () และโทร setState () เมื่อคุณได้รับเหตุการณ์
มีหลายสิ่งที่คุณสามารถใช้เพื่อตั้งค่าบัสเหตุการณ์ คุณสามารถสร้างอาร์เรย์ของผู้ฟังและในการเผยแพร่เหตุการณ์ผู้ฟังทั้งหมดจะได้รับเหตุการณ์ หรือคุณสามารถใช้สิ่งต่างๆเช่นEventEmitterหรือPostalJs
ฟลักซ์
ฟลักซ์นั้นเป็นบัสเหตุการณ์ยกเว้นผู้รับเหตุการณ์เป็นร้านค้า สิ่งนี้คล้ายกับระบบบัสเหตุการณ์พื้นฐานยกเว้นสถานะถูกจัดการนอก React
การติดตั้งฟลักซ์ดั้งเดิมดูเหมือนจะเป็นการพยายามจัดหากิจกรรมในลักษณะที่แฮ็ค
Reduxสำหรับฉันการใช้ Flux ที่ใกล้เคียงที่สุดกับการจัดหากิจกรรมซึ่งเป็นข้อดีของข้อได้เปรียบหลายประการของการจัดหากิจกรรมเช่นความสามารถในการเดินทางข้ามเวลา มันไม่ได้เชื่อมโยงกับ React อย่างเคร่งครัดและสามารถใช้กับไลบรารีมุมมองการทำงานอื่น ๆ
วิดีโอสอนการใช้ Redux ของ Egghead นั้นดีมากและอธิบายวิธีการใช้งานภายใน (มันง่ายจริงๆ)
เคอร์เซอร์
เคอร์เซอร์มาจากClojureScript / Omและใช้กันอย่างแพร่หลายในโครงการ React พวกเขาอนุญาตให้จัดการสถานะนอก React และปล่อยให้หลาย ๆ องค์ประกอบมีการเข้าถึงการอ่าน / เขียนในส่วนเดียวกันของรัฐโดยไม่จำเป็นต้องรู้อะไรเกี่ยวกับโครงสร้างส่วนประกอบ
มีการใช้งานหลายอย่างรวมถึงImmutableJS , React-cursorsและOmniscient
แก้ไข 2016 : ดูเหมือนว่าคนเห็นว่าเคอร์เซอร์ทำงานได้ดีสำหรับแอพขนาดเล็ก แต่มันไม่ได้ปรับขนาดได้ดีกับแอพที่ซับซ้อน อ้อมต่อไปไม่มีเคอร์เซอร์อีกต่อไป (ในขณะที่มันอ้อมที่แนะนำแนวคิดในขั้นต้น)
สถาปัตยกรรม Elm
สถาปัตยกรรม Elmเป็นสถาปัตยกรรมที่เสนอให้มีการใช้โดยภาษาเอล์มภาษาเอล์มแม้ว่า Elm ไม่ใช่ ReactJS สถาปัตยกรรม Elm ก็สามารถทำได้ใน React เช่นกัน
Dan Abramov ผู้เขียน Redux ได้ใช้งานสถาปัตยกรรม Elm โดยใช้ React
ทั้ง Redux และ Elm นั้นยอดเยี่ยมมากและมีแนวโน้มที่จะช่วยให้แนวคิดการจัดหาเหตุการณ์ในส่วนหน้าทั้งสองช่วยให้การดีบักการเดินทางข้ามเวลาเลิกทำ / ทำซ้ำทำซ้ำ ...
ความแตกต่างที่สำคัญระหว่าง Redux และ Elm คือ Elm มีแนวโน้มที่จะเข้มงวดมากขึ้นเกี่ยวกับการจัดการของรัฐ ใน Elm คุณไม่สามารถมีสถานะองค์ประกอบในตัวเครื่องหรือ mount / unmount hooks และการเปลี่ยนแปลง DOM ทั้งหมดจะต้องถูกกระตุ้นโดยการเปลี่ยนแปลงสถานะโกลบอล สถาปัตยกรรม Elm เสนอวิธีการปรับขนาดได้ที่ใบอนุญาตในการจัดการทั้งหมดของรัฐที่อยู่ภายในวัตถุไม่เปลี่ยนรูปเดียวในขณะ Redux เสนอวิธีการที่เชิญให้คุณจัดการได้มากที่สุดของรัฐในการเป็นวัตถุที่ไม่เปลี่ยนรูปเดียว
ในขณะที่โมเดลเชิงแนวคิดของ Elm นั้นสง่างามมากและสถาปัตยกรรมอนุญาตให้ปรับขนาดได้ดีบนแอพขนาดใหญ่ แต่ในทางปฏิบัติอาจทำได้ยากหรือมีส่วนร่วมมากขึ้นเพื่อให้ได้งานง่าย ๆ เช่นให้ความสำคัญกับอินพุตหลังจากติดตั้งหรือรวมเข้ากับห้องสมุดที่มีอยู่ ด้วยอินเทอร์เฟซที่จำเป็น (เช่นปลั๊กอิน JQuery) ปัญหาที่เกี่ยวข้อง
นอกจากนี้สถาปัตยกรรม Elm ยังเกี่ยวข้องกับรหัสสำเร็จรูปเพิ่มเติม ไม่ใช่ว่าจะเขียนอย่างละเอียดหรือซับซ้อน แต่ฉันคิดว่าสถาปัตยกรรม Elm นั้นเหมาะสมกับภาษาที่พิมพ์แบบคงที่
ไฟเบอร์กลาส
ไลบรารี่เช่น RxJS, BaconJS หรือ Kefir สามารถใช้ในการผลิตสตรีม FRP เพื่อจัดการการสื่อสารระหว่างส่วนประกอบ
คุณสามารถลองตัวอย่างเช่นRx-React
ผมคิดว่าการใช้ libs เหล่านี้ค่อนข้างคล้ายกับการใช้สิ่งที่เสนอภาษา ELM กับสัญญาณ
CycleJSกรอบไม่ได้ใช้ ReactJS แต่ใช้VDOM มันมีความคล้ายคลึงกันมากกับสถาปัตยกรรม Elm (แต่ใช้งานได้ง่ายกว่าในชีวิตจริงเพราะอนุญาตให้ vdom hooks) และใช้ RxJs อย่างกว้างขวางแทนฟังก์ชั่นและสามารถเป็นแรงบันดาลใจที่ดีถ้าคุณต้องการใช้ FRP ด้วย เกิดปฏิกิริยา วิดีโอ CycleJs Eggheadยินดีที่จะเข้าใจว่ามันทำงานอย่างไร
ซีเอสพี
ซีเอสพี (การสื่อสารลำดับกระบวนการ) ขณะนี้เป็นที่นิยม (ส่วนใหญ่เป็นเพราะไป / goroutines และ core.async / ClojureScript) แต่คุณสามารถใช้พวกเขายังอยู่ในจาวาสคริปต์ด้วยJS-CSP
James Long ได้ทำวิดีโอเพื่ออธิบายว่าสามารถใช้กับ React ได้อย่างไร
โศกนาฏกรรม
Saga เป็นแนวคิดเบื้องหลังที่มาจากโลก DDD / EventSourcing / CQRS หรือที่เรียกว่า "ผู้จัดการกระบวนการ" กำลังได้รับความนิยมจากโครงการredux-sagaซึ่งส่วนใหญ่เป็นการทดแทน redux-thunk สำหรับจัดการกับผลข้างเคียง (เช่นการเรียก API เป็นต้น) คนส่วนใหญ่ในปัจจุบันคิดว่าเป็นเพียงบริการสำหรับผลข้างเคียง แต่จริงๆแล้วเป็นเรื่องเกี่ยวกับการแยกส่วนประกอบ
มันเป็นคำชมที่น่าชื่นชมต่อสถาปัตยกรรม Flux (หรือ Redux) มากกว่าระบบการสื่อสารใหม่โดยสิ้นเชิงเพราะเทพนิยายปล่อยการกระทำของ Flux ในตอนท้าย แนวคิดคือถ้าคุณมี widget1 และ widget2 และคุณต้องการให้แยกออกจากกันคุณจะไม่สามารถดำเนินการกำหนดเป้าหมายการกระทำ widget2 จาก widget1 ได้ ดังนั้นคุณจึงทำการ widget1 เพียงการดำเนินการที่กำหนดเป้าหมายตัวเองและ saga เป็น "กระบวนการพื้นหลัง" ที่รับฟังการกระทำ widget1 และอาจส่งการกระทำที่เป็นเป้าหมาย widget2 เทพนิยายเป็นจุดเชื่อมต่อระหว่าง 2 วิดเจ็ต แต่วิดเจ็ตยังคงแยกจากกัน
หากคุณสนใจลองดูคำตอบของฉันที่นี่
ข้อสรุป
หากคุณต้องการดูตัวอย่างของแอพตัวเล็ก ๆ เดียวกันโดยใช้สไตล์ที่แตกต่างเหล่านี้ให้ตรวจสอบสาขาของที่เก็บนี้
ฉันไม่รู้ว่าตัวเลือกที่ดีที่สุดในระยะยาวคืออะไร แต่ฉันชอบที่ฟลักซ์ดูเหมือนว่าจะจัดหางาน
หากคุณไม่ทราบแนวคิดเกี่ยวกับการจัดหาเหตุการณ์ลองดูที่บล็อกการสอนแบบนี้: เปลี่ยนฐานข้อมูลจากภายในด้วย apache Samzaมันเป็นสิ่งที่ต้องอ่านเพื่อทำความเข้าใจว่าทำไม Flux ถึงดี (แต่นี่สามารถใช้กับ FRP ได้เช่นกัน )
ฉันคิดว่าชุมชนเห็นพ้องว่าการติดตั้ง Flux ที่มีแนวโน้มมากที่สุดคือReduxซึ่งจะช่วยให้นักพัฒนามีประสบการณ์การใช้งานที่มีประสิทธิผลมากขึ้นเนื่องจากการโหลดซ้ำร้อนแรง การสร้างรหัสสดที่น่าประทับใจนั้นเป็นไปได้ที่วิดีโอของ Inventor on Principleนั้นเป็นไปได้!