折腾:
【未解决】AntD Pro中支持剧本剧本编写时拖动排序单个对话
期间,需要对于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class DragSortingTable extends React.Component { state = { data: [ ] } } DragableDialogTable = DragDropContext(HTML5Backend)(DragSortingTable) render() { <this.DragableDialogTable / > } |
这种情况,想要在DragSortingTable的外部,去更新内部state的值
以实现可以在新增一行后,把新的列表的值,传递到可拖动去改变列表元素排序的内部
同时还需要,对于已经改变了排序的结果的值,在外部需要获取能
这样每次新增之前,才能用最新的被拖动排序后的列去新增
或许直接用props参数即可?
react js change state from outside
好像是用componentWillReceiveProps更合适
去试试
但是此处突然发现,此处还没发写成:
1 2 | / / DragableDialogTable = DragDropContext(HTML5Backend)(DragSortingTable) DragableDialogTable = DragDropContext(HTML5Backend)(DragSortingTable itemList = {demoItemList}) |
因为此处只是class DragSortingTable的调用而不是元素:
<DragSortingTable />
的调用,没法这么传递props
那貌似只能去试试:
直接给class DragSortingTable添加函数了
但是貌似是class的instance的函数,也没法加static的函数啊?
这样就没法修改每个instance的内部的state了?
突然想到了:
还是直接把DragSortingTable合并到当前的业务逻辑中,就可以了。
但是发现好像也不对,还是由于是class,没法直接直接合并
否则自己没法render自己
自己试试,能否添加额外函数,实现state的list的同步
或者加上额外的外部的全局变量去实现数据的同步
现在问题变成了:如何更新component class内部的state
react js change component class state
另外看到此处的代码中的DragDropContext的定义:

1 2 3 4 5 6 7 8 9 | /** * Wrap the root component of your application with DragDropContext decorator to set up React DnD. * This lets you specify the backend, and sets up the shared DnD state behind the scenes. * @param backendFactory The DnD backend factory * @param backendContext The backend context */ export declare function DragDropContext(backendFactory: BackendFactory, backendContext?: any): < TargetClass extends React.ComponentClass <any> | React.StatelessComponent< any >>(DecoratedComponent: TargetClass) => TargetClass & ContextComponent< any >; |
感觉是:
或许此处可以避开DragDropContext
因为此处不是root的element
然后希望不用传递TargetClass的方式,而是直接调用component,这样就可以传递参数和获取instance的state了。
去看看
中,是否一定要使用这种方式去调用
是我们需要的:

找了一下,终于找到这个example的代码了:
-》
-》
-》
-》
去参考看看代码:
1 2 | git clone https: //github .com /react-dnd/react-dnd .git |
然后出错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | ➜ react-dnd git:(master) npm install && npm start npm WARN deprecated istanbul-lib-hook@1.2.1: 1.2.0 should have been a major version bump > fsevents@1.2.4 install /Users/crifan/dev/dev_src/ReactJS/react-dnd/node_modules/fsevents > node install [fsevents] Success: "/Users/crifan/dev/dev_src/ReactJS/react-dnd/node_modules/fsevents/lib/binding/Release/node-v64-darwin-x64/fse.node" already installed Pass --update-binary to reinstall or --build-from-source to recompile > husky@0.14.3 install /Users/crifan/dev/dev_src/ReactJS/react-dnd/node_modules/husky > node ./bin/install.js husky setting up Git hooks done npm WARN prepublish-on-install As of npm@5, `prepublish` scripts are deprecated. npm WARN prepublish-on-install Use `prepare` for build steps and `prepublishOnly` for upload-only. npm WARN prepublish-on-install See the deprecation note in `npm help scripts` for more information. > react-dnd-master@ prepublish /Users/crifan/dev/dev_src/ReactJS/react-dnd > npm test > react-dnd-master@ test /Users/crifan/dev/dev_src/ReactJS/react-dnd > run-s lint build test_modules jest:cov > react-dnd-master@ lint /Users/crifan/dev/dev_src/ReactJS/react-dnd > tslint "packages/**/*.{ts,tsx}" -e "**/{lib,node_modules}/**" internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'typescript' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:594:15) at Function.Module._load (internal/modules/cjs/loader.js:520:25) at Module.require (internal/modules/cjs/loader.js:650:17) at require (internal/modules/cjs/helpers.js:20:18) at Object.<anonymous> (/Users/crifan/dev/dev_src/ReactJS/react-dnd/node_modules/tslint/lib/linter.js:22:10) at Module._compile (internal/modules/cjs/loader.js:702:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10) at Module.load (internal/modules/cjs/loader.js:612:32) at tryModuleLoad (internal/modules/cjs/loader.js:551:12) at Function.Module._load (internal/modules/cjs/loader.js:543:3) npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! react-dnd-master@ lint: `tslint "packages/**/*.{ts,tsx}" -e "**/{lib,node_modules}/**" ` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the react-dnd-master@ lint script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in : npm ERR! /Users/crifan/.npm/_logs/2018-08-06T05_55_53_490Z-debug.log ERROR: "lint" exited with 1. npm ERR! Test failed. See above for more details. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! react-dnd-master@ prepublish: `npm test` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the react-dnd-master@ prepublish script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in : npm ERR! /Users/crifan/.npm/_logs/2018-08-06T05_55_53_594Z-debug.log |
重新试试
结果npm install出错
算了。
只是去看代码,不运行demo了。


看了demo代码,也不是很容易懂。
刚看懂一点,好像是:
Container
只要用了:
1 | @DragDropContext(HTML5Backend) |

后,就可以正常的被别人调用了:

1 | < Container /> |
那此处也去试试是否可以这么用
1 2 3 4 5 6 7 8 9 10 11 12 | @DragDropContext(HTML5Backend) class DragSortingTable extends React.Component { ... } render() { return ( <DragSortingTable itemList={this.demoItemList} /> |
真的可以。
-》那么接下来,就容易改变list,然后传入新的list了。
然后期间遇到:
【未解决】Reactjs中传入属性变化后componentWillReceiveProps不工作没有调用
折腾:
【未解决】Reactjs中如何在Component的外部改变和获取state状态值
期间,
已经用代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | @DragDropContext (HTML5Backend) class DragSortingTable extends React.Component { state = { itemList: [], } constructor(props){ super (props) console.log( "DragSortingTable constructor: props=" , props) console.log( "this.props.itemList=" , this.props.itemList) this.state.itemList = this.props.itemList; } componentWillReceiveProps(nextProps){ console.log( "DragSortingTable componentWillReceiveProps: nextProps=" , nextProps) console.log( "this.props.itemList=" , this.props.itemList) if (this.props.itemList) { this.setState({itemList: this.props.itemList}) console.log( "updated this.state.itemList=" , this.state.itemList) } } components = { body: { row: DragableBodyRow, }, } moveRow = (dragIndex, hoverIndex) = > { const { itemList } = this.state; const dragRow = itemList[dragIndex]; this.setState( update(this.state, { itemList: { $splice: [[dragIndex, 1 ], [hoverIndex, 0 , dragRow]], }, }), ); } render() { console.log( "DragSortingTable render: this.state.itemList=" , this.state.itemList) return ( <Table columns = {columns} dataSource = {this.state.itemList} components = { this.components } onRow = {(record, index) = > ({ index, moveRow: this.moveRow, })} / > ); } } @connect (({ loading, script, topic }) = > ({ submitting: loading.effects[ 'script/submitRegularForm' ], script, topic, })) @Form .create() export default class ScriptCreate extends PureComponent { 。。。 handleAddDialog(){ console.log( "handleAddDialog" ) const curItemList = this.state.dialogList let newItemList = curItemList const curItemNum = curItemList.length const newItemNum = curItemNum + 1 let newDialog = { key: `${newItemNum}`, speakerOrSong: `new speaker ${newItemNum}`, contentOrAddress: `new content ${newItemNum}`, } console.log( "newDialog=" , newDialog) newItemList.push(newDialog) console.log( "newItemList=" , newItemList) this.setState({ dialogList: newItemList}) console.log( "this.state.dialogList=" , this.state.dialogList) } render() { return ( <DragSortingTable itemList = {this.state.dialogList} / > |
实现了,当点击添加按钮时,去新增一行,且用
this.setState({ dialogList: newItemList})
更新了state,但是DragSortingTable中的componentWillReceiveProps却没运行
react props changed componentWillReceiveProps not called
* if its not receiving a new props object from the redux store
猜测是此处用了redux而导致此处state变化了,但是componentWillReceiveProps也没有运行
如何解决呢?
想起来别人提起来的,强制刷新,试试:
1 | this.forceUpdate() |
就可以了。
【总结】
当reactjs使用了redux,则会导致setState后,子元素中的state变量变化了,但是子元素中的componentWillReceiveProps也不允许,从而无法实现刷新显示的效果
解决办法是,对于父元素中,setState后,加上:
1 | this.forceUpdate() |
即可强制刷新。则字元素也就正常了。