如何在React中使用键/值对象

3

我正在努力使用React中的一个对象,我试图访问正在返回的键:值(我可以成功地console.log)。

我尝试过的所有示例都会导致映射每个字符或抛出对象子错误,我感到很困惑。

  componentDidMount() {
    this.gun.on('auth', () => this.thing());
  }

  thing() {
    this.gun.get('todos').map((value, key) => { console.log(key, value) }
    );
  }

  handleChange = e => this.setState({ newTodo: e.target.value })

  add = e => {
    e.preventDefault()
    this.gun.get('todos').set(this.state.newTodo)
    this.setState({ newTodo: '' })
  }

  del = key => this.gun.get(key).put(null)

  render() {
    return <>
      <Container>
        <div>Gun</div>
        <div>
          <form onSubmit={this.add}>
            <input value={this.state.newTodo} onChange={this.handleChange} />
            <button>Add</button>
          </form>
          <br />
          <ul>
            {this.state.todos.map(todo => <li key={todo.key} onClick={_ => this.del(todo.key)}>{todo.val}</li>)}
          </ul>
        </div>
      </Container></>
  }
}

gun 对象已经正确初始化了吗? - Dacre Denny
是的,这个代码示例是我在控制台中打印我试图在React中映射的数据的工作状态。 - jhizzle207
好的,为了澄清 - 你想让你的React组件更新以显示你对gun对象所做的更改? - Dacre Denny
理想情况下,我希望能够使用那些数据。但是在这个阶段,如果我尝试直接映射它,会出现错误,因为它是一个对象;如果我映射到一个数组,似乎无法保留键。 - jhizzle207
1个回答

1

有几种方法可以将组件状态与其他数据源(例如gun对象)同步-一种简单的方法是在组件的state中缓存要渲染的todo数据副本。

这是通过调用setState()函数完成的,当调用时,会导致组件重新渲染。在您的组件的render()方法中,更改todos状态字段将更新显示列表。

使用此方法,您需要确保在对gun对象的todos数据进行更改时,还通过setState()更新组件的todo状态,如下所示:

constructor(props) {
    super(props)

    /* Setup inital state shape for component */
    this.state = {
        todos : [], 
        newTodo : ''
    }
}

mapTodos() {
    return this.gun.get('todos').map((value, key) => ({ key : key, val : value }));
}

componentDidMount() {
    this.gun.on('auth', () => this.mapTodos());
}

handleChange = e => this.setState({ newTodo: e.target.value })

add = e => {
    e.preventDefault()
    this.gun.get('todos').set(this.state.newTodo)

    /* When adding a todo, update the todos list of the component's internal state
    to cause a re-render. This also acts as a cache in this case to potentially speed
    up render() by avoiding calls to the gun.get() method */
    this.setState({ newTodo: '', todos : this.mapTodos() })
}

del = key => {
    this.gun.get(key).put(null)

    /* Call setState again to update the todos field of the component state to
    keep it in sync with the contents of the gun object */
    this.setState({ newTodo: '', todos : this.mapTodos() })
}

render() {
    return <Container>
        <div>Gun</div>
        <div>
            <form onSubmit={this.add}>
            <input value={this.state.newTodo} onChange={this.handleChange} />
            <button>Add</button>
            </form>
            <br />
            <ul>
            {this.state.todos.map(todo => <li key={todo.key} onClick={ () => this.del(todo.key) }>{todo.val}</li>)}
            </ul>
        </div>
    </Container>
}

mapTodo的实际上没有在this.state.todos上设置数据,如果我添加了它,它是未定义的(我期望它会抛出一个对象错误,但不确定为什么它是未定义的,控制台日志返回了正确的数据) - jhizzle207
如果我删除 this.mapTodos 后面的括号,那么就可以解决 undefined 的问题,但是我们又回到了 this.state.todos.map 不是一个函数的问题(可能是因为它是一个对象?) - jhizzle207
回到原点:错误:对象不是有效的React子元素(发现具有键{_}的对象)。如果您想呈现一组子元素,请改用数组。 - jhizzle207
@jhizzle207对您的<li>上的onClick处理程序进行了小改动 - 对此有任何进展吗? - Dacre Denny
有趣的是,如果你用 {JSON.stringify(todo)} 替换 {todo.val} 会发生什么? - Dacre Denny
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接