Meteor + React 如何设置大量输入元素的值并修改后

IT技术 javascript meteor reactjs
2021-05-09 05:16:52

我是流星和react的新手。假设我的react组件中有这个:

getMeteorData() {
    var myForm = ProjectForm.findOne({_id:this.props.router.params._id});
    var projects = ProjectForm.find({});
    return {myForm:myForm,projects:projects};
    // doing a console.log(myForm); would give you something like
    /*
    input1:my text 1
    input2:some other text
    input3:something else
    etc....
    */
  },
  renderListProjects() {

    return this.data.projects.map(function(projectform,i) {
      return <li key={"li"+i}><a href={Meteor.absoluteUrl()+'project/' + projectform.username +'/' +projectform._id} key={"a"+i}>Project {projectform._id}</a></li>;
    });
  },
  getInitialState() {
     return Projects.findOne({this.props.router.params._id}, {sort: {createdAt: -1}});
  },
  render() {
    return (
      <div>
      <ul>{this.renderListProjects()}</ul>
      <form>
         <span>Hello this is some text</span>
         <input type="text" ref="input1" />
         <p>Blah blah this is boring</p>
         <input type="text" ref="input2" />
         <img src="image-of-a-kangaroo.png" />
         <input type="text" ref="input3" />
         <ul>
            <li>Buy brocolli</li>
            <li>Buy oregano</li>
            <li>Buy milk</li>
         </ul>
         <input type="text" ref="input4" />
         ...
         <textarea ref="input100"></textarea>
         <input type="text" ref="input101" />
         <p><strong>Yes, I like pizza!</strong>  But my porcupine gets sick eating pizza.</p>
         ...
      </form>
      </div>
    );

我想要做的是将 的值分配给this.data.myFormrender() 函数中的每个表单字段。但是,当我执行类似的操作<input type="text" ref="input1" value={this.data.myForm.input1} />,然后转到 Web 浏览器并将光标放在该字段上时,我无法修改该值。按键盘上的键不会更改该输入字段的值。此外,我在这个 html 表单中有大约 250 个输入字段。我真的不想做任何数据输入。我宁愿只使用某种循环来遍历this.data.myForm并将其分配给相应的表单字段。但是当我尝试这样做时,我遇到了有关未找到 DOM 或未加载 DOM 的问题。所以我尝试在 componentDidMount() 中编写一些代码,但后来出现了其他错误。

任何人都可以指出我如何有效地将我的所有this.data.myForm数据绑定到我的表单字段并允许我在之后编辑表单字段的正确方向吗?

其他要求

  1. 如果有人从 中单击 link1,renderListProjects然后从 中单击 link2 renderlistProjects,则表单必须显示 link2 的值projectform._id

  2. 在 DOM 中,href="project/_id"必须存在用于 SEO 和 WCAG 合规性属性。

尝试

我试图将 renderListProjects 重新定义为

  renderListProjects() {
    var pj = this
    return this.data.projects.map(function(projectform,i) {
      return <li key={"li"+i}><a onClick={pj.click(projectform._id)} href={Meteor.absoluteUrl()+'project/' + projectform.username +'/' +projectform._id} key={"a"+i}>Project {projectform._id}</a></li>;
    });
  },
click(id) {
    var currentApp = ProjectForm.findOne({_id:id}, {sort: {createdAt: -1}});
    this.setState({input36:input36});
  },

但是当我运行我的meteor+react 项目时,我的浏览器崩溃了,因为某种无限循环正在发生。

2个回答

你创建的是 React 所谓的受控输入这意味着 React 已经在输入中声明了您的值以对应于this.data.myForm.input1指向的任何内容。

为了能够更改输入字段,您需要做的是添加一个负责更新值的 onChange 处理程序。文档非常简单,但我在下面添加了一个小示例来说明它。

class Form extends React.Component {
  constructor() {
    super();
    this.state = {
      myForm: {
        inputs: [
          {value: 1}, {value: 2}, {value: 3}
        ]
      }
    };
  }
  onChange = (index, event) => {
    let inputs = this.state.myForm.inputs.slice(0);
    inputs[index] = {
      value: parseInt(event.target.value, 10)
    };

    this.setState({
      myForm: {
        inputs: inputs
      }
    })
  }
  render() {
    return (<form>
      {this.state.myForm.inputs.map((input, index) => {
        return (<input onChange={this.onChange.bind(null, index)} value={input.value} key={index} />);
      }, this)}
      </form>);
  }
};

ReactDOM.render(<Form />, document.querySelector('#c'));

这段代码解决了这个问题

getMeteorData() {
    var myForm = ProjectForm.findOne({_id:this.props.router.params._id});
    var projects = ProjectForm.find({});
    return {myForm:myForm,projects:projects};
    // doing a console.log(myForm); would give you something like
    /*
    input1:my text 1
    input2:some other text
    input3:something else
    etc....
    */
  },
  clickLoadForm(appId)
  {
    var currentApp = Projects.findOne({appId}, {sort: {createdAt: -1}});
    var state = new Object();
    var refs = this.refs;
    Object.keys(refs).map(function(prop,index){
      state[prop] = typeof currentApp[prop] == 'undefined' ? "" : currentApp[prop];
    });
    this.setState(state);
  },
  handleChange: function(e) {
    if(!e.target.id) return;
    if(typeof e.target.id == 'undefined') return;
    var state = new Object();
    state[e.target.id] = e.target.value;

    this.setState(state);
  },
  renderListProjects() {

    return this.data.projects.map(function(projectform,i) {
      return <li key={"li"+i}><a onClick={_this.clickLoadForm.bind(_this,projectform._id)} href={Meteor.absoluteUrl()+'project/' +projectform._id} key={"a"+i}>Project {projectform._id}</a></li>;
    });
  },
  getInitialState() {
     return Projects.findOne({this.props.router.params._id}, {sort: {createdAt: -1}});
  },
  render() {
    return (
      <div>
      <ul>{this.renderListProjects()}</ul>
      <form>
         <span>Hello this is some text</span>
         <input type="text" ref="input1" id="input1" onChange={this.handleChange} />
         <p>Blah blah this is boring</p>
         <input type="text" ref="input2" id="input2" onChange={this.handleChange} />
         <img src="image-of-a-kangaroo.png" />
         <input type="text" ref="input3" id="input3" onChange={this.handleChange} />
         <ul>
            <li>Buy brocolli</li>
            <li>Buy oregano</li>
            <li>Buy milk</li>
         </ul>
         <input type="text" ref="input4" id="input4" onChange={this.handleChange} />
         ...
         <textarea ref="input100" id="input100" onChange={this.handleChange}/>
         <input type="text" ref="input101" id="input101" onChange={this.handleChange} />
         <p><strong>Yes, I like pizza!</strong>  But my porcupine gets sick eating pizza.</p>
         ...
      </form>
      </div>
    );

总而言之,我的变化是:

  1. 创建了一个renderListProjects()函数
  2. 创建clickLoadForm()函数并在renderListProjects()
  3. 创建了该handleChange()函数并确保它通过 onChange 对中的每个元素进行引用render()
  4. 确保中的每个元素render()都有一个与 ref 相同的 id