折腾:
【未解决】AntD Pro中支持剧本剧本编写时拖动排序单个对话
期间,需要对于
class DragSortingTable extends React.Component { state = { data: [ ] } } DragableDialogTable = DragDropContext(HTML5Backend)(DragSortingTable) render() { <this.DragableDialogTable /> }
这种情况,想要在DragSortingTable的外部,去更新内部state的值
以实现可以在新增一行后,把新的列表的值,传递到可拖动去改变列表元素排序的内部
同时还需要,对于已经改变了排序的结果的值,在外部需要获取能
这样每次新增之前,才能用最新的被拖动排序后的列去新增
或许直接用props参数即可?
react js change state from outside
好像是用componentWillReceiveProps更合适
去试试
但是此处突然发现,此处还没发写成:
// 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的定义:
/** * 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的代码了:
-》
-》
-》
-》
去参考看看代码:
git clone https://github.com/react-dnd/react-dnd.git
然后出错:
➜ react-dnd git:(master) npm install && npm start npm WARN deprecated [email protected]: 1.2.0 should have been a major version bump > [email protected] 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 > [email protected] 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
只要用了:
@DragDropContext(HTML5Backend)
后,就可以正常的被别人调用了:
<Container />
那此处也去试试是否可以这么用
@DragDropContext(HTML5Backend) class DragSortingTable extends React.Component { ... } render() { return ( <DragSortingTable itemList={this.demoItemList} />
真的可以。
-》那么接下来,就容易改变list,然后传入新的list了。
然后期间遇到:
【未解决】Reactjs中传入属性变化后componentWillReceiveProps不工作没有调用
折腾:
【未解决】Reactjs中如何在Component的外部改变和获取state状态值
期间,
已经用代码:
@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也没有运行
如何解决呢?
想起来别人提起来的,强制刷新,试试:
this.forceUpdate()
就可以了。
【总结】
当reactjs使用了redux,则会导致setState后,子元素中的state变量变化了,但是子元素中的componentWillReceiveProps也不允许,从而无法实现刷新显示的效果
解决办法是,对于父元素中,setState后,加上:
this.forceUpdate()
即可强制刷新。则字元素也就正常了。