考虑这个伪代码:
component.js
...
import {someFunc} from "./common_functions.js"
export default class MyComp extends Component {
constructor(props) {
super(props);
this.someFunc = someFunc.bind(this);
this.state = {...};
}
_anotherFunc = () = > {
....
this.someFunc();
}
render() {
...
}
}
common_functions.js
export function someFunc() {
if(this.state.whatever) {...}
this.setState{...}
}
如何将函数someFunc()
绑定到Component
的上下文?我在各种组件中使用它,因此在一个文件中收集它们是有意义的。现在,我收到错误“无法读取未定义的内容”。 this
的背景未知......
答案 0 :(得分:3)
您不能在组件外部设置State,因为它是组件的本地状态。如果需要更新共享的状态,请创建存储(redux存储)。
在您的情况下,您可以在一个位置定义someFunction并将其传递给特定的状态变量或整个状态。在someFunction中完成后,返回修改后的状态并使用setState在组件中将其更新回来。
export function someFunc(state) {
if(state.whatever) {...}
const newState = { ...state, newValue: whateverValue }
return newState
}
_anotherFunc = () = > {
....
const newState = this.someFunc(this.state);
this.setState({newValue: newState});
}
答案 1 :(得分:1)
有一种函数形式的setState甚至可以在组件之外使用。
这是可能的,因为setState的签名是:
* @param {object|function} partialState Next partial state or function to
* produce next partial state to be merged with current state.
* @param {?function} callback Called after state is updated.
见Dan的推文:https://twitter.com/dan_abramov/status/824308413559668744
答案 2 :(得分:0)
这一切都取决于你想要达到的目标。乍一看,我可以看到2个选项。一个创建子组件和两个:使用redux,因为redux在所有子组件之间提供单一状态。
第一个选项:
export default class parentClass extends Component {
state = {
param1: "hello".
};
render() {
return (
<Child param1={this.state.param1}/>
);
}
}
class Child extends Component {
render() {
console.log(this.props.param1);
return (
<h1>{this.props.param1}</h1>
);
}
}
现在上面的子组件将从其父渲染函数传递的props中定义props.param1
。
上述方法可行,但我可以看到你正试图建立一套“共同的”功能。选项2提供了一种通过为您的应用程序/项目创建单一状态来实现此目的的方法。 如果你还没有使用过redux,那么一旦你掌握了它,它就会非常简单易用。我现在将跳过设置http://redux.js.org/docs/basics/UsageWithReact.html。
像这样制作一个减速器:
import * as config from './config';//I like to make a config file so it's easier to dispatch my actions etc
//const config.state = {param1: null}
//const config.SOME_FUNC = "test/SOME_FUNC";
export default function reducer(state = config.state, action = {}) {
switch(action.type) {
case config.SOME_FUNC:
return Object.assign({}, state, {
param1: action.param1,
});
break;
default:
return state;
}
}
}
将它添加到商店的Reducer中。
将所有组件包装在提供程序中。
ReactDOM.render(
<Provider store={store} key="provider">
<App>
</Provider>,
element
);
现在,您将能够在提供程序的所有子组件上使用redux connect!
像这样:
import React, {Component} from 'react';
import {connect} from 'react-redux';
@connect(
state => (state),
dispatch => ({
someFunc: (param1) => dispatch({type: config.SOME_FUNC, param1: param1}),
})
)
export default class Child extends Component {
eventFunction = (event) => {
//if you wanted to update the store with a value from an input
this.props.someFunc(event.target.value);
}
render() {
return (
<h1>{this.props.test.param1}</h1>
);
}
}
当你习惯了redux时,请查看https://github.com/redux-saga/redux-saga。这是你的最终目标!萨加斯很棒!如果你被卡住了,请告诉我!
答案 3 :(得分:0)
最好显然是使用某种管理它的外部库。正如其他人所说,Redux和MobX对此有好处。使用高阶组件来包装所有其他组件也是一种选择。
然而,这是上述方法的另一种解决方案:
您可以使用标准的javascript类(不是React组件)并将this
传递给您从该类调用的函数。
这很简单。我在下面创建了一个简单的例子,其中状态从另一个类的函数改变;看一看:
class MyApp extends React.Component {
constructor() {
super();
this.state = {number: 1};
}
double = () => {
Global.myFunc(this);
}
render() {
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.double}>Double up!</button>
</div>
);
}
}
class Global {
static myFunc = (t) => {
t.setState({number: t.state.number*2});
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"><div>
答案 4 :(得分:0)
您定义回调并管理全局状态的父组件示例:
export default class Parent extends Component {
constructor() {
super();
this.state = {
applyGlobalCss: false,
};
}
toggleCss() {
this.setState({ applyGlobalCss: !this.state.applyGlobalCss });
}
render() {
return (
<Child css={this.state.applyGlobalCss} onToggle={this.toggleCss} />
);
}
}
&#13;
然后在子组件中,您可以使用道具和回调,如:
export default class Child extends Component {
render() {
console.log(this.props.css);
return (
<div onClick={this.props.onToggle}>
</div>
);
}
}
Child.propTypes = {
onToggle: PropTypes.func,
css: PropTypes.bool,
};
&#13;
答案 5 :(得分:0)
这不是React的实践,它可能会导致很多问题/错误,但是js允许这样做:
模块A:
export function your_external_func(thisObj, name, val) {
thisObj.setSate((prevState) => { // prevState - previous state
// do something with prevState ...
const newState = { // new state object
someData: `This is updated data ${ val }`,
[name]: val,
};
return newState
});
}
然后在您的react-app模块中使用它:
import { your_external_func } from '.../your_file_with_functions';
class YourReactComponent extends React.Component {
constructor(props, context) {
super(props, context);
this.state={
someName: '',
someData: '',
};
}
handleChange = (e) => {
const { target } = event;
const { name } = target;
const value = target.type === 'checkbox' ? target.checked : target.value;
your_external_func(this, name, value);
}
render() {
return (<span>
{ this.state.someData }
<br />
<input
name='someName'
value={ this.state.someName }
onChange={ this.handleChange }
/>
</span>);
}
}
这是一个愚蠢的例子:)只是为了向您展示如何做到这一点
答案 6 :(得分:0)
以您的示例为例,我可以看到您可以通过一种简单的方法来完成此操作,而不是传递任何内容。
由于您要更新状态的值,因此只需从函数本身返回状态即可。
只需使要在组件中使用的函数异步,然后等待该函数返回一个值并将状态设置为该值即可。
ref.documentId
在SomeOtherFile.js中
ref.id