代码之家  ›  专栏  ›  技术社区  ›  mexicanChica

React Hooks窗体处理:使用多个字符串项和一个数组项更新对象的状态

  •  0
  • mexicanChica  · 技术社区  · 6 年前

      const [recipe, setRecipe] = useState({
        title: '',
        description: '',
        ingredients: [],
        instructions: '',
        tags: 'none'
      }); 
    

    本教程最初包含所有字符串项,因此以下代码可以完美地更新状态:

        setRecipe({ ...recipe, [e.target.name]: e.target.value });
      }
    

              <input
                type='text'
                placeholder='Title'
                name='title'
                value={title}
                onChange={onChange}
              />
    

    现在我已经将其中一个项目更改为数组,它不再工作。我试过几种方法,例如:

     const [test, setTest] = useState({
        ingredients: ['bread', 'milk', 'honey']
      });
    
     const [query, setQuery] = useState('');
    
      const updateQuery = e => {
    
        setQuery(e.target.value);
      };
    
      const addItem = e => {
        e.preventDefault();
    
        setTest(test => ({ ingredients: [...test.ingredients, query] }));
      };
    
    return (
    
              <div>
                <button className='btn btn-light btn-block' onClick={addItem}>
                  Add ingredient
                </button>
                <input
                  type='text'
                  placeholder='Description'
                  name='ingredients'
                  value={ingredients}
                  onChange=(updateQuery)
                />
              </div>
              <div>
                {test.ingredients.map(data => (
                  <ul key={data}>{data}</ul>
                ))}
              </div>
    
      );
    

    我正在努力寻找解决办法。

    如有帮助,不胜感激。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Incepter    6 年前

    您提供的代码需要一些格式(aka: onChange={onChange} onChange 你的输入值 query 而不是成分)

    另外,在编辑旧状态时,您没有重新获取它。

    const [test, setTest] = React.useState({
        nonArray: 0,
        ingredients: ["bread", "milk", "honey"]
      });
    

    然后我给你换了个附件,看起来像:

    const addItem = e => {
        e.preventDefault();
        setTest(old => ({ ...old, ingredients: [...old.ingredients, query] }));
        setQuery("");
      };
    

    请检查一下这个 working codesandbox 基本上包含你的代码。

        2
  •  0
  •   Stark Jeon    6 年前

    在我看来,你需要在addItem中使用useCallback,比如

    const updateQuery = useCallback(e => {
    
        setQuery(e.target.value);
      },[]);
    
    const addItem = useCallback(e => {
        e.preventDefault();
    
        setTest(test => ({ ingredients: [...test.ingredients, query] }));
      },[query]);
    
    

    这是钩子原理,如果你想了解这个原理,你可以搜索 Principle of useCallback

    如果你想知道简单的方法,我可以告诉你一件事。 在“渲染组件”中, addItem

        3
  •  0
  •   Chris    6 年前

    问题在于这一行: setTest(test => ({ ingredients: [...test.ingredients, query] })

    当使用react类组件时,最好设置状态而不传播整个先前的状态 this.setState({ ingredients: [...test.ingredients, query] }) this.setState 与之前的状态。

    在反应钩, React.useState 不进行合并,所以你必须像 setState(test => ({ ...test, ingredients: [...test.ingredients, query] }) .

    test 在组件的顶部。我建议将 测试 内部参数 setTest