【问题标题】:Changes to react component not showing in view - one character change shows up in onChange对反应组件的更改未显示在视图中 - onChange 中显示了一个字符更改
【发布时间】:2019-01-06 23:37:19
【问题描述】:

问题:

我似乎无法更改输入标签中的占位符(在<Details /> 内)。

预期行为:

输入标签将使用组件的状态及其handleChange 函数进行更新。

实际行为:抱歉,这是一项正在进行中的工作!

对输入字段所做的更改仅注册一个字符。

示例选中FileName 中的所有字符并删除它们会在handleChange 函数中的console.log() 中将它们显示为已删除。但是,视图上的字段永远不会更改,而是保持相同的值。

我的尝试:

我尝试使用propsstate 来处理更改,但没有任何效果。我猜我可能不得不像使用 FileItem 一样将更改提升到祖先,但我不确定。

实际代码:

import * as React from "react";
import { IFileModel, IFileWrapper } from "../models/fileModel";
import { Fortress } from "../../dependencies/fortress";

let divStyle = {
    width: "50px",
    border: "1px solid #000",
    padding: "5px",
    margin: "5px"
};

declare let config : {[key : string] : string};

const $F = new Fortress(config);

export class DetailsPanel extends React.Component<IFileModel, any> {
    constructor(props : IFileModel) {
        super(props); 
        this.state = { 
            isDisplayed : false 
        };
        this.toggle = this.toggle.bind(this);  
    }  

    toggle() {
        let newIsCollapsed = !(this.state.isDisplayed);
        this.setState({ isDisplayed : newIsCollapsed })
    }   

    render() {
        return(
            <div>
                <div>
                    <input className="button" type="submit" value={ (!this.state.isDisplayed) ? "Show Panel" : "Hide Panel" } onClick={this.toggle} />
                </div>
                { this.state.isDisplayed ? <Details {...this.props} /> : null }
            </div>
        );
    }
}

export class Details extends React.Component <IFileModel, any> {

    constructor(props : IFileModel) {
        super(props);
        this.state = {
            currentFile : this.props
        };
        this.onSubmit = this.onSubmit.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }
    // http://localhost/admin/shared/file/SaveFile/?
    /*
        FileId: 1
        FileName: shirt.pdf
        LCID: 2057
        FileVariation: 0
        DisplayName: shirt.png
        OriginalFileName: shirt__1_3_2057.pdf
        CategoryId: 0
        FileType: 1
        FileExtension: png
        FileSize: 419920
        Width: 615
        Height: 462
        FileData: 
        AllowedVariantTypes: 0
        RequireAuthorization: 0
        AdminId: 1
        CreationDate: /Date(1450692426023)/
        ModifyDate: /Date(1450692426023)/
        ExpiryDate: /Date(253402300799997)/
    */

    handleChange(e : any) { 
        console.log(e.target.name, e.target.value);
        this.setState({ [e.target.name] : e.target.value });
    }

    onSubmit() {
        const state = this.state.currentFile;
        console.log($F.writeAdminUrl("shared", "file", "SaveFile"));
        console.log(JSON.stringify(state));
        // fetch($F.writeAdminUrl("shared", "file", "SaveFile"), {
        //     method: "POST",
        //     headers: {
        //         "credentials": "same-origin", 
        //         "mode": "no-cors",
        //         "Content-Type" : "application/json"
        //     },
        //     body : JSON.stringify({ fileId : state.fileId })
        // })
    }

    render() {
        const currentFile = this.props;
        return(
            <div style={{border: "1px dashed black", padding: "4px"}}>
                <div>
                    <p> File Name: </p>
                    <input type="text" value={currentFile.fileName} name="fileName" onChange={this.handleChange} />
                </div>
                <div>
                    <p> Image: </p>
                    <input type="text" value={currentFile.imageUrl} name="imageUrl" onChange={this.handleChange} />
                </div>
                <div>
                    <p> Creation date: </p>
                    <input type="text" value={currentFile.creationDate} name="creationDate" onChange={this.handleChange} />
                </div>
                <div>
                    <p> LCID: </p>
                    <input type="text" name="LCID" value={currentFile.LCID} onChange={this.handleChange} />
                </div>
                <div>
                    <input onClick={(currentFile) ? this.onSubmit : null} type="submit"/>
                </div>
            </div>
        );
    }
}

export class FileItem extends React.Component<IFileModel> {

    constructor(props : IFileModel) {
        super(props);
        this.onSelect = this.onSelect.bind(this);
    }

    onSelect() {
        this.props.onSelect(this.props); 
    }

    render() {
        return (
            <div className="fileItem" style={{ width: "100px", height: '150px', float: 'left' }} onClick={this.onSelect}>
                <img src={"http://localhost/content/image/" + this.props.imageUrl} style={divStyle} />
                {this.props.fileName}
                <button className="edit" />
            </div>
        );
    } 
}

export class FileList extends React.Component<any, any> {

    constructor(props : any) {
        super(props);
        this.state = { files: [], skip: 0, take: 10 }
        this.increaseTake = this.increaseTake.bind(this);
        this.onSelect = this.onSelect.bind(this);
    }

    getImages(skip : number, take : number, shouldAdd : boolean) {


        var that = this;
        fetch("http://localhost/admin/shared/file/GetImages?take=" + take + "&skip=" + skip + "&FileType=0&_2331223a3543as", {
            credentials: "same-origin", mode: "no-cors"
        })
            .then(function(response) {
                return response.json();
            })
            .then(function (results) {
                var newFiles = results.data.map((file : any) => ({
                    imageUrl: file.OriginalFileName,
                    fileName: file.DisplayName,
                    fileId: file.FileId,
                    creationDate: file.CreationDate,
                    LCID: file.LCID
                }));

                if (shouldAdd) {
                    newFiles = that.state.files.concat(newFiles);
                }

                that.setState({ files: newFiles });

            });
    }

    onSelect(file : IFileModel) { 
        this.props.onFileSelected(file);
    }

    increaseTake() {
        var currentSkip = this.state.skip + 10;
        this.setState({ skip: currentSkip });
        this.getImages(currentSkip, this.state.take, true);
    }

    componentWillMount() {
        // perfom ajax call
        this.getImages(0, this.state.take, true);
    }


    render() {

        return (<div>

            {this.state.files.map((item: IFileModel, index: number) =>
                <FileItem key={index} {...item} onSelect={this.onSelect} />
                )
            }
            <div style={{ clear: 'both' }}></div>
            <div onClick={this.increaseTake}>take more</div>
        </div>)
    }
}

export class FileGallery extends React.Component <any, any> {
    constructor(props : any) {
        super(props);
        let fm : IFileModel;
        this.state = {
            sidebarCollapsed : false,
            selectedFile : fm
        }; 

        this.onFileSelected = this.onFileSelected.bind(this);
    }

    onFileSelected(file : IFileModel) {
        this.setState({ selectedFile : file }); 
    }

    render() {
        const selectedFile = this.state.selectedFile;
        return (
            <div>
                <div className="FileGalleryHeader">
                    <div>Galley</div>
                    <div>Upload</div>
                </div>
                <div className="FileGalleyMain" style={{ width: "80%", display : 'block', height:"400px", overflow : "auto", float : "left"}}>
                    <FileList onFileSelected={this.onFileSelected}/>
                </div>
                <div style={{ width: "20%", display: "block", float : "right", height: "800px"}}>
                    <DetailsPanel {...selectedFile} onSubmit={(selectedFile) ? selectedFile.onSubmit : null } />
                </div>
        </div>);
    }
}

型号:

export interface IFileModel {
    fileId: number;
    fileName: string;
    categoryId: number;
    fileType: number;
    fileExtension: string;
    fileSize: string;
    width: number;
    height: number;
    creationDate: string;
    imageUrl: string;
    LCID: string;
    onSubmit: Function;
    onSelect: Function; 
}

export interface IFileWrapper {
    file: IFileModel;   
} 

【问题讨论】:

    标签: reactjs typescript dom hoisting


    【解决方案1】:

    就我查看的代码而言,可能有两个问题:

    1。您在Details 中设置了错误的状态

    handleChange(e : any) { 
        console.log(e.target.name, e.target.value);
        this.setState({ [e.target.name] : e.target.value });
    }
    

    这应该是:

    handleChange(e : any) { 
        console.log(e.target.name, e.target.value);
        this.setState({ currentFile: {
            ...this.state.currentFile,
            [e.target.name]: e.target.value
        });
    }
    

    2。您不应将任何props 设置为input 值,而应改为state

        const currentFile = this.props;
        return(
            <div style={{border: "1px dashed black", padding: "4px"}}>
                <div>
                    <p> File Name: </p>
                    <input type="text" value={currentFile.fileName} name="fileName" onChange={this.handleChange} />
                </div>
    

    这应该是:

        const currentFile = this.state;
        return(
            <div style={{border: "1px dashed black", padding: "4px"}}>
                <div>
                    <p> File Name: </p>
                    <input type="text" value={currentFile.fileName} name="fileName" onChange={this.handleChange} />
                </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      相关资源
      最近更新 更多