Javascript 单击子组件时,更新父组件的状态会返回一个错误,显示“0”;无法读取属性…”;

Javascript 单击子组件时,更新父组件的状态会返回一个错误,显示“0”;无法读取属性…”;,javascript,reactjs,Javascript,Reactjs,我试图在单击子组件时更新父组件状态。我似乎能够从子组件传递所需的信息,并且当我在console.log中记录站点名称时,它就工作了。当我尝试更新状态时,问题开始出现。它返回一个错误,说明“无法读取未定义的属性'setState'。我不确定它为什么这样做 子组件 export default function StationListItem(props) { const boldString = (str, substr) => { var strRegExp = new Re

我试图在单击子组件时更新父组件状态。我似乎能够从子组件传递所需的信息,并且当我在console.log中记录站点名称时,它就工作了。当我尝试更新状态时,问题开始出现。它返回一个错误,说明“无法读取未定义的属性'setState'。我不确定它为什么这样做

子组件


export default function StationListItem(props) {
  const boldString = (str, substr) => {
    var strRegExp = new RegExp(substr, "gi");
    var newString = str.match(strRegExp);
    var x = str.replace(newString, "<b>" + newString + "</b>");
    return x;
  };

  const { name, query, action } = props;

  return (
    <li
      onClick={() => {
        action(name);
      }}
      name={name}
      dangerouslySetInnerHTML={{ __html: boldString(name, query) }}
    ></li>
  );
}
import "../../App.sass";
import StationListItem from "../Account/StationListItem";

const searchListStyles = {
  margin: 0,
  padding: 0,
  listStyleType: "none",
  border: "1px solid #ccc",
  borderTop: "0px",
  borderRadius: "0 0 5px 5px",
  height: "100%",
  maxHeight: "228px",
  overflow: "scroll",
};

export default class SaveFavouriteStations extends Component {
  constructor() {
    super();

    this.state = {
      searchField_isFocused: false,
      query: "",
      stationsArr: [],
      filteredArr: [],
      selectedArr: ["Leigh-on-Sea"],
      selected: "",
    };
  }

  componentDidMount() {
    fetch("api/stations")
      .then((response) => {
        return response.json();
      })
      .then((stations) => {
        this.setState({ stationsArr: stations });
      });
  }

  handleSearch(e) {
    this.setState({ [e.target.name]: e.target.value.toLowerCase() });

    const filtered = this.state.stationsArr.filter((station) => {
      if (
        station.station_name
          .toLowerCase()
          .includes(this.state.query.toLowerCase()) ||
        station.crs_code.toLowerCase().includes(this.state.query.toLowerCase())
      ) {
        return station;
      }
    });

    this.setState({ filteredArr: filtered });
  }

  searchFocusHandler(e) {
    console.log(e);
    this.setState({ searchField_isFocused: true });
  }

  clickHandler(name) {
    this.setState({
      selected: name,
    });
  }

  render() {
    const {
      filteredArr,
      selectedArr,
      query,
      searchField_isFocused,
    } = this.state;

    const matchingStations = filteredArr.map((station) => {
      return (
        <StationListItem
          key={station._id}
          name={station.station_name}
          query={query}
          action={this.clickHandler}
        />
      );
    });

    const selected = selectedArr.map((selected) => {
      return selected;
    });

    return (
      <div className="section favourite-stations">
        <h1>Favourite Stations</h1>
        <input
          autoComplete="off"
          className="text-input"
          type="text"
          name="query"
          placeholder="Search for a station..."
          onChange={(e) => {
            this.handleSearch(e);
          }}
          onFocus={() => {
            this.setState({ searchField_isFocused: true });
          }}
          onMouseDown={() => {
            this.setState({ searchField_isFocused: false });
          }}
        />
        {searchField_isFocused ? (
          <ul style={searchListStyles}>
            {query.length >= 2 ? (
              matchingStations
            ) : (
              <div style={{ padding: "10px 0", color: "#ccc" }}>
                Enter a station name or code
              </div>
            )}
          </ul>
        ) : (
          ""
        )}
        <div>{selectedArr.length >= 1 ? selected : "no stations selected"}</div>
      </div>
    );
  }
}




导出默认函数StationListItem(道具){
常量boldString=(str,substr)=>{
var stregexp=新的RegExp(substr,“gi”);
var newString=str.match(strRegExp);
var x=str.replace(newString,“+newString+”);
返回x;
};
const{name,query,action}=props;
返回(
  • { 行动(名称); }} name={name} DangerouslySetinerHTML={{{uuuuHTML:boldString(名称,查询)} >
  • ); }
    父组件

    
    export default function StationListItem(props) {
      const boldString = (str, substr) => {
        var strRegExp = new RegExp(substr, "gi");
        var newString = str.match(strRegExp);
        var x = str.replace(newString, "<b>" + newString + "</b>");
        return x;
      };
    
      const { name, query, action } = props;
    
      return (
        <li
          onClick={() => {
            action(name);
          }}
          name={name}
          dangerouslySetInnerHTML={{ __html: boldString(name, query) }}
        ></li>
      );
    }
    
    import "../../App.sass";
    import StationListItem from "../Account/StationListItem";
    
    const searchListStyles = {
      margin: 0,
      padding: 0,
      listStyleType: "none",
      border: "1px solid #ccc",
      borderTop: "0px",
      borderRadius: "0 0 5px 5px",
      height: "100%",
      maxHeight: "228px",
      overflow: "scroll",
    };
    
    export default class SaveFavouriteStations extends Component {
      constructor() {
        super();
    
        this.state = {
          searchField_isFocused: false,
          query: "",
          stationsArr: [],
          filteredArr: [],
          selectedArr: ["Leigh-on-Sea"],
          selected: "",
        };
      }
    
      componentDidMount() {
        fetch("api/stations")
          .then((response) => {
            return response.json();
          })
          .then((stations) => {
            this.setState({ stationsArr: stations });
          });
      }
    
      handleSearch(e) {
        this.setState({ [e.target.name]: e.target.value.toLowerCase() });
    
        const filtered = this.state.stationsArr.filter((station) => {
          if (
            station.station_name
              .toLowerCase()
              .includes(this.state.query.toLowerCase()) ||
            station.crs_code.toLowerCase().includes(this.state.query.toLowerCase())
          ) {
            return station;
          }
        });
    
        this.setState({ filteredArr: filtered });
      }
    
      searchFocusHandler(e) {
        console.log(e);
        this.setState({ searchField_isFocused: true });
      }
    
      clickHandler(name) {
        this.setState({
          selected: name,
        });
      }
    
      render() {
        const {
          filteredArr,
          selectedArr,
          query,
          searchField_isFocused,
        } = this.state;
    
        const matchingStations = filteredArr.map((station) => {
          return (
            <StationListItem
              key={station._id}
              name={station.station_name}
              query={query}
              action={this.clickHandler}
            />
          );
        });
    
        const selected = selectedArr.map((selected) => {
          return selected;
        });
    
        return (
          <div className="section favourite-stations">
            <h1>Favourite Stations</h1>
            <input
              autoComplete="off"
              className="text-input"
              type="text"
              name="query"
              placeholder="Search for a station..."
              onChange={(e) => {
                this.handleSearch(e);
              }}
              onFocus={() => {
                this.setState({ searchField_isFocused: true });
              }}
              onMouseDown={() => {
                this.setState({ searchField_isFocused: false });
              }}
            />
            {searchField_isFocused ? (
              <ul style={searchListStyles}>
                {query.length >= 2 ? (
                  matchingStations
                ) : (
                  <div style={{ padding: "10px 0", color: "#ccc" }}>
                    Enter a station name or code
                  </div>
                )}
              </ul>
            ) : (
              ""
            )}
            <div>{selectedArr.length >= 1 ? selected : "no stations selected"}</div>
          </div>
        );
      }
    }
    
    
    
    
    导入“../../App.sass”;
    从“./Account/StationListItem”导入StationListItem;
    常量searchListStyles={
    保证金:0,
    填充:0,
    listStyleType:“无”,
    边框:“1px实心#ccc”,
    边框顶部:“0px”,
    边界半径:“0 0 5px 5px”,
    高度:“100%”,
    最大高度:“228px”,
    溢出:“滚动”,
    };
    导出默认类saveFavoriteExtends组件{
    构造函数(){
    超级();
    此.state={
    searchField_聚焦:false,
    查询:“”,
    StationSharer:[],
    筛选标准:[],
    已选择的DARR:[“Leigh on Sea”],
    选定:“,
    };
    }
    componentDidMount(){
    获取(“api/站点”)
    。然后((响应)=>{
    返回response.json();
    })
    。然后((站)=>{
    this.setState({stationsArr:stations});
    });
    }
    handleSearch(e){
    this.setState({[e.target.name]:e.target.value.toLowerCase()});
    const filtered=this.state.stationsArr.filter((站)=>{
    如果(
    station.station\u名称
    .toLowerCase()
    .includes(this.state.query.toLowerCase())||
    station.crs_code.toLowerCase().includes(this.state.query.toLowerCase())
    ) {
    返回站;
    }
    });
    this.setState({filteredar:filteredar});
    }
    搜索聚焦处理器(e){
    控制台日志(e);
    this.setState({searchField_isFocused:true});
    }
    clickHandler(名称){
    这是我的国家({
    所选名称:,
    });
    }
    render(){
    常数{
    过滤过滤器,
    选择DARR,
    查询
    searchField_专注于,
    }=本州;
    const matchingStations=Filteredar.map((站)=>{
    返回(
    );
    });
    const selected=selectedArr.map((已选)=>{
    返回选中的;
    });
    返回(
    喜爱的电台
    {
    本研究(e);
    }}
    onFocus={()=>{
    this.setState({searchField_isFocused:true});
    }}
    onMouseDown={()=>{
    this.setState({searchField_isFocused:false});
    }}
    />
    {searchField\u是焦点(
    
      {query.length>=2( 配对站 ) : ( 输入站点名称或代码 )}
    ) : ( "" )} {selectedArr.length>=1?选中:“未选择任何电台”} ); } }
    对于构造函数中的函数,您必须
    绑定此

    this.clickHandler = this.clickHandler.bind(this)
    //other functions
    
    或者,更改声明类型:

    clickHandler = (e) => {//your code}
    //other functions
    

    将此解决方案应用于
    handleSearch、clickHandler、searchFocusHandler
    函数

    您必须为构造函数中的函数绑定此

    this.clickHandler = this.clickHandler.bind(this)
    //other functions
    
    或者,更改声明类型:

    clickHandler = (e) => {//your code}
    //other functions
    

    将此解决方案应用于
    handleSearch、clickHandler、searchFocusHandler
    函数

    将事件处理程序转换为箭头函数,否则
    未定义:

    handleSearch(e) {
       // this is undefined 
       this.setState(); // => "Cannot read property 'setState' of undefined"
    }
    
    handleSearch = (e) => {
       // this is defined
       this.setState(); // works :)
    }
    

    将事件处理程序转换为箭头函数,否则此
    未定义:

    handleSearch(e) {
       // this is undefined 
       this.setState(); // => "Cannot read property 'setState' of undefined"
    }
    
    handleSearch = (e) => {
       // this is defined
       this.setState(); // works :)
    }
    

    谢谢这起作用了。我确实认为这是问题所在,但没有正确实现代码。谢谢!这起作用了。我确实认为这就是问题所在,但没有正确地实现代码。