【问题标题】:Handling local data in Relay Modern在 Relay Modern 中处理本地数据
【发布时间】:2018-04-11 12:48:14
【问题描述】:

我一直在传递从突变返回的数据来处理 Reactjs 中的表单验证。此模式不仅限于表单验证,还适用于其他具有相似要求的组件,其中某些内容被变异/查询,并且响应数据仅用于更新 UI。

概念:

<LoginForm/> 组件呈现登录表单并提交带有表单数据的loginMutation。验证发生在后端,如果验证捕获到任何错误,突变将使用字段errors 解决,其中包含键值对,其中键表示表单字段,值描述值的问题。想法是将errors 对象传递给<LoginForm/>,以便组件可以渲染/更新以在UI 中显示错误。

errors: { 
  username: "Username must not be empty", 
  password: "Password must not be empty"
}

挑战:

解析后的数据(errors)应该以什么方式传递给<LoginForm/>?最直接的锤钉方法是将回调函数从<LoginForm/> 传递给loginMutation,并在onComplete() 内部使用响应对象调用它。像这样的:

onCompleted: (response, errors) => { setLoginFormState(resonse.errors) }

那么在<LoginForm/>中就会有

setLoginFormState(validationState){ 
    this.setState({errors: validationState })
}

最后我们可以像这样在<LoginForm/> 中相应地更新 UI

render(){
  const { errors } = this.state;
  const usernameClass = errors.username ? 'danger' : 'primary';
  const passwordClass = errors.password ? 'danger' : 'primary';
  return (
    <div>
      <input name="username" className={usernameClass} />
     <input name="username" className={passwordClass} />
    </div>
  )

}

我正在寻找一种减少意大利面的方法。

我也期待宣布的schema extensions 功能,该功能目前缺少文档。似乎它的目的是通过允许我们将本地状态(例如 UI 状态)与从查询/突变中获取的持久数据混合来解决这个问题。

【问题讨论】:

    标签: reactjs relay relaymodern react-relay


    【解决方案1】:

    React-Relay-Rebind 是 Relay 现代和 React 的组件范围状态管理。

    我创建了这个库来提供一个声明性 API,用于管理由 Relay 突变返回的本地状态。该库目前正在积极开发中。欢迎打开新问题并提交 PR!

    React-Relay-Rebind 允许您将突变绑定到组件。绑定意味着组件将接收突变返回的状态作为道具。

    使用示例

    import { rebind } from 'react-relay-rebind';
    import { loginMutation } from './loginMutation';
    
    class MyComponent extends React.component {
    
      handleSubmit(){
        this.props.mutations.login(this.props.relay, this.state);
      }
    
      handleFieldChange(fieldName){
        return (e) => {
          // Login mutation stateProxy
          const { login } = this.props;
    
          this.setState({ [fieldName]: e.target.value() });
    
          // Set login mutation to initial state
          this.login.resetState();
        }
      }
    
      render(){
        const { errors } = this.props.login.state;
        const usernameClassname = errors.username ? 'has-error' : '';
        const passwordClassname = errors.password ? 'has-error' : '';
    
        return (
           <div>
            <input
              className={usernameClassname}
              name="username"
              type="text"
              onChange={this.handleFieldChange('username')}
              value={username} />
            <br/>
            <input
              className={passwordClassname}
              name="password"
              type="password"
              onChange={this.handleFieldChange('password')}
              value={password} />
            <br/>
            <input type="submit" onClick={this.handleSubmit} value="Login"/>
          </div>
      }
    }
    
    const mutations = {
      login: {
        mutation: LoginMutation,
        initialState: {
          errors: {
            username: null,
            password: null,
          },
        },
      },
    };
    export default rebind(mutations)(MyComponent);
    

    【讨论】:

    • 我想我更喜欢onCompletedonError 在处理此类问题时用于提交突变的显式回调。也许你会发现写onCompleted: this._setStateFromMutation...和_setStateFromMutation = (response) =&gt; { ... }
    猜你喜欢
    • 2017-11-23
    • 2018-04-09
    • 2018-05-15
    • 2018-04-08
    • 2020-01-18
    • 2017-10-15
    • 2019-09-23
    • 2018-05-17
    • 2017-11-27
    相关资源
    最近更新 更多