index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
(
<App/>
),
document.querySelector('#root')
)
App.js
import React, { Component } from 'react'
import Add from './components/Add'
import List from './components/List'
/*
1.引入Provider包裹需要共享數據的結構,並且設置data,這是data就是共享數據
2.需要使用共享數據的組件,就引入withData高階組件做修飾。
*/
import {Provider} from './HOC/withData'
const data = {
list: [],
title: 'app',
name: 'zhangsan',
userid: '1293'
};
export default class App extends Component {
render() {
return (
<Provider data={data}>
<div className="app">
<Add/>
<List/>
</div>
</Provider>
)
}
}
HOC/withData.js 高階組件
import React, {Component} from 'react'
const DataContext = React.createContext({
globalData: {}
});
export class Provider extends Component{
constructor(props) {
super(props);
//props.data state.globalData
this.state = {
globalData: {...props.data}
}
this.methods = {
change: (newData)=>{
this.setState({
globalData: {
...this.state.globalData,
...newData
}
});
}
}
}
render(){
return (
<DataContext.Provider value={{globalData: this.state.globalData, ...this.methods }}>
{this.props.children}
</DataContext.Provider>
);
}
}
export const withData = (Com, handleData = {})=>{
class withData extends Component{
constructor(props) {
super(props);
let newHandleData = {};
Object.keys(handleData).forEach(key=>{
let newFunc = handleData[key].bind(this, this.dispatch);
newHandleData[key] = newFunc;
});
this.state = {
newHandleData
}
}
render(){
return <Com {...this.context.globalData} {...this.state.newHandleData} {...this.props}/>
}
dispatch=(cb)=>{
let result = cb(this.context.globalData);
this.context.change(result);
}
}
withData.contextType = DataContext;
return withData;
}
Add.js 需要使用 withData 修飾的組件
import React, { Component } from 'react'
import {withData} from '../HOC/withData'
let id = 1;
class Add extends Component {
render() {
return (
<div>
<h1>新增</h1>
<input type="text" ref={el=>(this.input=el)}/>
<button onClick={this.addAction.bind(this)}>新增</button>
</div>
)
}
addAction(){
this.props.add({
value: this.input.value,
id: id++,
status: 'todo'
});
this.input.value = '';
}
}
const handleData = {
add(dispatch, params){
dispatch((globalData)=>{
return {
list: [...globalData.list, params]
}
});
}
}
export default withData(Add, handleData);