【问题标题】:React: How to access component refs from Redux/Flux actions?React:如何从 Redux/Flux 操作访问组件引用?
【发布时间】:2017-08-05 09:54:54
【问题描述】:

当实现像 Redux 或 MobX 这样的状态容器时,你的状态和事件通常被移动到一个单独的类或对象中,不再可以读取 refs。

例如,在普通组件中:

import Alert from Alert.js;

class Dummy extends React.Component {
  constructor(props) {
    super(props);

    this.state = { clicked: false }
  }

  handleClick() {
    fetch('api').then(function(){
      this.setState({ clicked: true });
      this._alert.show('Cool response!');
    });
  }

  render() {
    return (
      <div>
        <Alert ref={a => this._alert = a} />
        <Button onClick={this.handleClick}/>
      </div>
    )
  }
}

如果我点击按钮,一旦服务器请求完成,状态就会更新并触发警报。在一些 modal 和 alert 库中使用这样的 refs 是很常见的。

现在,在 Redux(或任何 Flux 实现)中,该 fetch() 将存在于一个动作中,该动作存在于一个单独的文件中,该文件无权访问 this._alert

在不重写外部“警报”库的情况下维护功能的最佳方法是什么?

【问题讨论】:

  • 在你的行动中你可以返回一个承诺 I.E. api 调用,您可以执行以下操作:this.props.fetchSomething.then(() =&gt; this._alert.show('Cool response!') 您只需要确保您在操作中返回了承诺。
  • 返回一个 Promise 是个好主意,但是您需要使用一些中间件来让您的操作返回诸如 redux-promise-middleware 或类似的承诺

标签: javascript reactjs redux flux


【解决方案1】:

作为说明,我来自您的帖子:https://dannyherran.com/2017/03/react-redux-mobx-takeaways/

这从一开始就是错误的。 Refs 不应该在组件之间共享,因为这会耦合它们。组件的设计应完全相互分离,并根据赋予它们的状态做出反应。

问题是 ref 没有告诉你组件本身的状态,你不知道它是否已安装,你甚至不知道它是否存在,所以你在玩一些 volatile 的东西。

所以让我们解耦一切并适当地利用 react/redux 的力量,所有代码都应该以这种方式组织:

1。减速机:

Reducer 将保持警报的显示状态。 现在,整个应用程序中的任何组件都可以访问它,独立于 refs,因此该组件是否实际存在并不重要。

const DummyPageReducer = function(state, action) 
{
    if (state === undefined) 
    {
        state = 
        {
            alertShow: false
        };
    }

    switch(action.type) 
    {
        case 'ALERT_DISPLAY':
            return Object.assign({}, state, { alertShow: action.display });
    }
    return state;
}

2。动作和异步动作:

调整警报显示设置的操作,以及执行获取并产生正确结果的异步操作。

export const ALERT_DISPLAY = 'ALERT_DISPLAY '
export function alertDisplay(display) 
{
    return {
        type: ALERT_DISPLAY,
        display
    }
}

export function showAlert() 
{   
    return function (dispatch) 
    {  
        fetch('api').then(function()
        {
            dispatch(alertDisplay(true))
        });

    }

}

3。连接组件:

连接的组件。无需共享 refs,将使用 ref,但组件将对其给定的 props 做出反应并相应地设置 Alert。

import Alert from Alert.js;

class Dummy extends React.Component 
{
    constructor(props) 
    {
        super(props);

        this.setAlert = this.setAlert.bind(this);
    }

    setAlert()
    {
        if(this.props.alertShow)
            this._alert.show('Cool response!');
        else
            this._alert.hide();

    }

    componenDidMount()
    {
        setAlert();
    }

    componentDidUpdate(prevProps, prevState)
    {
        if(prevProps.alertShow !== this.props.alertShow)
            setAlert();
    }

    render() 
    {
        return 
        (
            <div>
                <Alert ref={a => this._alert = a} />
                <Button onClick={this.props.showAlert}/>
            </div>
        )
    }
}
Dummy = connect(

    state => 
    ({
        alertShow: state.Dummy.alertShow
    }),

    dispatch =>
    ({
        showAlert: () => dispatch(showAlert(true))
    })

)(Dummy);

【讨论】:

  • 我认为您忘记在连接的 Dummy 组件上导入您的 showAlert 操作。
【解决方案2】:

首先,你有没有尝试在handleClick中使用箭头功能?

handleClick() {
    fetch('api').then(() => {
        this.setState({ clicked: true });
        this._alert.show('Cool response!');
    });
}

这可能会影响this的上下文

另一方面,如果您使用 Redux,则应该创建两个操作。 比如fetchAPI()APIfetched()

【讨论】:

    猜你喜欢
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2016-06-27
    相关资源
    最近更新 更多