Javascript 使用Firebase中的对象设置状态

Javascript 使用Firebase中的对象设置状态,javascript,arrays,reactjs,firebase,firebase-realtime-database,Javascript,Arrays,Reactjs,Firebase,Firebase Realtime Database,我在设置React中组件的状态时遇到问题。该组件称为“搜索”,并使用react select。完整的组成部分如下: class Search extends React.Component { constructor(props){ super(props); let options = []; for (var x in props.vals){ options.push({ value: props.vals[x], label: props.vals

我在设置React中组件的状态时遇到问题。该组件称为“搜索”,并使用react select。完整的组成部分如下:

class Search extends React.Component {
  constructor(props){
    super(props);
    let options = [];
    for (var x in props.vals){
      options.push({ value: props.vals[x], label: props.vals[x], searchId: x });
    };
    this.state = {
      inputValue: '',
      value: options
    };
  }

  handleChange = (value: any, actionMeta: any) => {
    if(actionMeta.action == "remove-value"){
      this.props.onRemoveSearch({ searchId: actionMeta.removedValue.searchId })
    }
    this.setState({ value });
  };

  handleInputChange = (inputValue: string) => {
    this.setState({ inputValue });
  };

  handleSearch = ({ value, inputValue }) => {
    this.setState({
      inputValue: '',
      value: [...value, createOption(inputValue)], // Eventually like to take this out...
    });
    this.props.onSearch({ inputValue });
  }

  handleKeyDown = (event: SyntheticKeyboardEvent<HTMLElement>) => {
    const { inputValue, value } = this.state;
    if (!inputValue) return;
    switch (event.key) {
      case 'Enter':
      case 'Tab':
        this.handleSearch({
          value,
          inputValue
        });
        event.preventDefault();
    }
  };

  render() {
    const { inputValue, value } = this.state;
    return (
        <div className="search">
            <div className="search__title">Search</div>
            <Tooltip
              content={this.props.tooltipContent}
              direction="up"
              arrow={true}
              hoverDelay={400}
              distance={12}
              padding={"5px"}
              >
              <CreatableSelect
                className={"tags"}
                components={components}
                inputValue={inputValue}
                isMulti
                menuIsOpen={false}
                onChange={this.handleChange}
                onInputChange={this.handleInputChange}
                onKeyDown={this.handleKeyDown}
                placeholder="Add filters here..."
                value={value}
              />
            </Tooltip>
        </div>
    );
  }
}

module.exports = Search;
类搜索扩展了React.Component{
建造师(道具){
超级(道具);
让期权=[];
用于(道具VAL中的变量x){
push({value:props.vals[x],label:props.vals[x],searchId:x});
};
此.state={
输入值:“”,
价值:期权
};
}
handleChange=(值:任意,actionMeta:任意)=>{
if(actionMeta.action==“删除值”){
this.props.onRemoveSearch({searchId:actionMeta.removedValue.searchId})
}
this.setState({value});
};
handleInputChange=(inputValue:string)=>{
this.setState({inputValue});
};
handleSearch=({value,inputValue})=>{
这是我的国家({
输入值:“”,
value:[…value,createOption(inputValue)],//最后我想把这个拿出来。。。
});
this.props.onSearch({inputValue});
}
handleKeyDown=(事件:KeyboardEvent)=>{
const{inputValue,value}=this.state;
如果(!inputValue)返回;
开关(事件键){
“输入”案例:
案例“选项卡”:
这是我的手感({
价值
输入值
});
event.preventDefault();
}
};
render(){
const{inputValue,value}=this.state;
返回(
搜寻
);
}
}
module.exports=搜索;
您可能已经注意到我在构造函数中所做的奇怪事情。这是因为我需要使用firebase数据库中的数据,它是对象形式的,但react select需要一个对象数组 具有“值”和“标签”属性。以下是我的数据:

为了弥补这个差距,我编写了一个for-in循环来创建数组(称为options),并将其传递给state.value


问题:因为我在使用这个“for in”循环,React无法识别道具何时被更改。因此,react select组件不会重新渲染。如何传递这些道具(在父组件内或在搜索组件内修改它们),以便搜索组件重新渲染?

我建议不要使用
状态。你所做的只是将道具复制到你的状态。您可以直接在
render()
方法中使用道具

我认为您使用
状态是因为您需要根据用户操作进行更新。在这种情况下,可以将此状态提升到父组件中

class Parent extends React.Component {
  constructor() {
    this.state = { value: //structure should be the same as props.vals in ur code };
  }
  render() {
    return (
      <Search vals={this.state.value}/>
    );
  }
}

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

    this.state = {
      inputValue: '',
    };
  }

  render() {
    const { inputValue } = this.state;
    const { vals } = this.props;
    let options = [];
    for (var x in vals){
      options.push({ value: vals[x], label: vals[x], searchId: x });
    };
    return (
        <div className="search">
            <div className="search__title">Search</div>
            <Tooltip
              content={this.props.tooltipContent}
              direction="up"
              arrow={true}
              hoverDelay={400}
              distance={12}
              padding={"5px"}
              >
              <CreatableSelect
                value={options}
              />
            </Tooltip>
        </div>
    );
  }
}

module.exports = Search;
类父级扩展React.Component{
构造函数(){
this.state={value://结构应与ur代码中的props.vals相同};
}
render(){
返回(
);
}
}
类搜索扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
输入值:“”,
};
}
render(){
const{inputValue}=this.state;
const{vals}=this.props;
让期权=[];
用于(var x,单位为VAL){
push({value:vals[x],label:vals[x],searchId:x});
};
返回(
搜寻
);
}
}
module.exports=搜索;

如果您的组件未卸载,则不会重新运行构造函数。因此,除非卸载,否则for-in循环不会重新运行。另一个选项是将选项移动到渲染方法中,或者添加ComponentDidUpdateEyes的其他生命周期方法,我使用的是值状态,因为react select组件依赖于它。您能否举一个简短的例子,说明“提升”状态到父组件的含义?我怎样才能做到呢?谢谢。很多事情都取决于我的搜索组件中的“值”状态,所以我对如何提升它有点不清楚。请查看我的更新答案以获得一个简短的演示。如果不深入了解你的代码,我就无法提供一个有效的演示。您可能还需要更新事件处理程序函数。