千巷猫影
继续我的评论:这是我的做法的完整示例。我正在使用 mqttws31.js 库连接到蚊子。如果您需要,请告诉我。我有加载 redux 存储的 app.js 和 App.jsx 中的应用程序。App.jsx 处理我的 wsClient 函数,但您可以将它们移动到其他文件。这是重新渲染我的组件的 Redux Connect 函数和 mapstateToProps。如果 props 改变,组件会再次渲染商店.js:import { createStore } from 'redux'import { composeWithDevTools } from 'redux-devtools-extension';import { createReducer } from '@reduxjs/toolkit'; // I'm using the toolkit hereconst reducer = createReducer(initialState, { SET_ONE: (state, action) => { state.items[action.key] = action.value }, SET_ALL: (state, action) => { state.items = action.data }})const initialState = { items: {}}const store = createStore(reducer,initialState);export default store;应用程序.js:import store from './store';import { Provider } from 'react-redux';import App from './app.jsx';window.addEventListener('load', (event) => { ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.querySelector('#app-root') );});应用程序.jsx:import React from 'react';import store from './store';import '../vendor/paho-mqtt/mqttws31.js'; // the mqtt libconst MQTT = window.Paho.MQTT; // the MQTT objectclass App extends React.Component { state = { activeTab: 0, items: {}, //from redux wsClientStatus: 'Not Connected' } shouldComponentUpdate = (nextProps, nextState) => { const { wsClientStatus } = this.state if (wsClientStatus !== nextState.wsClientStatus) { return true } return false; } componentDidMount = () => { this.wsClientInit(); } render () { //console.log('app render') const { wsClientStatus } = this.state; // for a status bar const state = this.state return ( <DimmableLight topics={{DMX:{read:'DMX_0', write:'WEB/DMX_0'}}} bpTopic={"WEB/DI01"} location="WC" publish={this.wsClientPublish} /> ) } wsClient = new MQTT.Client("YOUR HOST", 9001, "myclientid_" + parseInt(Math.random() * 100, 10)); wsClientSetCallBacks = () => { const that = this; this.wsClient.onConnectionLost = function (responseObject) { console.log("Ws client:: connexion lost..."); that.setState({wsClientStatus: 'Not connected'}); //reconnect that.wsClientConnect(that.wsClient); }; this.wsClient.onMessageArrived = function (message) { //Do something with the push message you received var data = JSON.parse(message.payloadString); console.log("Received <- " + message.destinationName + ":: ", data); //update the store //only one topic / all topics if (Object.keys(data).length > 1) store.dispatch({type:'SET_ALL', data:data}) else store.dispatch({type:'SET_ONE', key:Object.keys(data)[0], value:data[Object.keys(data)[0]]}) }; } wsClientInit = () => { this.wsClientSetCallBacks(); this.wsClientConnect(this.wsClient); window.wsClientPublish = this.wsClientPublish; // to publish manualy within chrome console } wsClientConnect = (wsClient) => { const _this = this console.log("Ws client:: tentative de connexion..."); _this.setState({wsClientStatus: 'Tentative de connexion'}); wsClient.connect({ timeout: 15, useSSL: true, userName: 'USER_NAME', password: 'USER_PASSWORD', //Gets Called if the connection has sucessfully been established onSuccess: function () { console.log("Ws client:: Connecté."); _this.setState({wsClientStatus: 'Connecté'}); wsClient.subscribe('unipi_data/#', {qos: 0}); wsClient.subscribe('WEB/#', {qos: 0}); setTimeout(function() {this.wsClientPublish("getAllData", "unipi_system/data", 1);}, 1000); }, //Gets Called if the connection could not be established onFailure: function (message) { console.log("Ws client:: La Connexion a échoué: " + message.errorMessage); setTimeout(function() { _this.wsClientConnect(wsClient); }, 1000); } }); } wsClientPublish = (payload, topic, qos = 1) => { //Send your message (also possible to serialize it as JSON or protobuf or just use a string, no limitations) var message = new MQTT.Message(JSON.stringify(payload)); message.destinationName = topic; message.qos = qos; this.wsClient.send(message); console.log("publish -> ", topic, payload, qos); }}export default App;就我而言,DimmableLight.jsx:import React from 'react';import { connect } from 'react-redux'; //connect child to the redux storeimport { withStyles } from '@material-ui/core/styles';import Card from '@material-ui/core/Card';import CardHeader from '@material-ui/core/CardHeader';import CardActions from '@material-ui/core/CardActions';import CardContent from '@material-ui/core/CardContent';import Typography from '@material-ui/core/Typography';import Slider from '@material-ui/core/Slider';import IconButton from '@material-ui/core/IconButton';import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';import Bulb from './Bulb' // an SVGclass DimmableLight extends React.Component { static defaultProps = { data: {}, topics: {DMX:{read:'DMX_0', write:'WEB/DMX_0'}}, // override from props in App.jsx bpTopic: "WEB/DI01", location: 'Chambre' } state = { } // IMPORTANT: update the component only when selected topics change shouldComponentUpdate = (nextProps, nextState) => { const { data } = this.props let shouldUpdate = false; data && Object.keys(data).map((key) => { if (data[key] !== nextProps.data[key]) shouldUpdate = true }) return shouldUpdate; } handleChange = (evt, value) => { const { publish, topics } = this.props; // publish passed from props in App.jsx publish(parseInt(value), topics.DMX.write); } onBpPressed = (evt) => { const { publish, bpTopic } = this.props publish(parseInt(1), bpTopic); } onBpReleased = (evt) => { const { publish, bpTopic } = this.props publish(parseInt(0), bpTopic); } render () { const { data, topics, location, classes } = this.props //console.log('render dimmable', location) return ( <Card className={classes.root}> <CardHeader title={location}> </CardHeader> <CardContent className={classes.cardContent}> <Bulb luminosity={(data[topics.DMX.read] || 0)/254}/> </CardContent> <CardActions className={classes.cardActions}> <Slider min={0} max={254} value={data[topics.DMX.read] || 0} onChange={this.handleChange} aria-labelledby="continuous-slider" /> <IconButton color="primary" variant="contained" onMouseDown={this.onBpPressed} onMouseUp={this.onBpReleased}> <RadioButtonCheckedIcon/> </IconButton> </CardActions> </Card> ) }}const styles = theme => ({ root: { [theme.breakpoints.down('sm')]: { minWidth: '100%', maxWidth: '100%', }, [theme.breakpoints.up('sm')]: { minWidth: 180, maxWidth: 180, }, }, cardContent: { textAlign: 'center' }, cardActions: { margin: '0px 10px 0px 10px', '& > :first-child': { margin: '0 auto' } } });// Connect only wanted topics, set first in defaultProps to be sure to have them in ownPropsconst mapStateToProps = (state, ownProps) => { let data = [] Object.keys(ownProps.topics).map(topicKey => { data[ownProps.topics[topicKey].read] = state.items[ownProps.topics[topicKey].read] || 0 }); return { data: data }} export default connect(mapStateToProps)(withStyles(styles, {withTheme: true})(DimmableLight))