2017-02-21 17 views
0

В моем приложении react мне нужно проверить параметр id в URL-адресе, а затем визуализировать представление соответственно (то есть разные представления в случае успешной и неудачной проверки). Вот пример кода:Component Mounting для проверки параметра url перед представлением рендеринга в ReactJs

routes.js

// just relevant lines of code: 
import React from 'react'; 
import { Route, IndexRoute } from 'react-router'; 
import Foo from '../containers/foo'; 

const AppRoutes = (
    <Route component={Base} path="/"> 
    <Route component={Foo} path="/url/:id"/> 
    </Route> 
); 
export default AppRoutes;  

класса Foo

import React, { Component } from 'react'; 
import { isValid } from '../service';  

class Foo extends Component { 
    state = { 
    check : true 
    } 
    componentWillMount(){ 
    if (isValid(this.props.params.id) == false || 'undefined') { 
     console.log(isValid(this.props.params.id)); 
     this.setState({ 
     check : false 
     }); 
    } 
    } 
    render() { 
    if (!this.state.check){ 
     return(...); 
    }else{ 
     return(...); 
    } 
    }; 
} 
export default Foo; 

service.js

"use strict"; 
function createCORSRequest(method, url) { 
    var xhr = new XMLHttpRequest(); 
    if ("withCredentials" in xhr) { 
    // XHR for Chrome/Firefox/Opera/Safari. 
    xhr.open(method, url, true); 
    } else if (typeof XDomainRequest != "undefined") { 
    // XDomainRequest for IE. 
    xhr = new XDomainRequest(); 
    xhr.open(method, url); 
    } else { 
    // CORS not supported. 
    xhr = null; 
    } 
    return xhr; 
} 

function fetchId(method, url, id, callback){ 
    var xhr = createCORSRequest(method, url); 
    if (!xhr) return; 
    xhr.addEventListener("readystatechange", callback); 
    xhr.setRequestHeader("content-type", "application/json"); 
    xhr.send(JSON.stringify(query)); 
} 

function isValid(id){ 
    let url = 'https://some/api/url/'; 
    return fetchId('POST', url, id, function(){ 
    return (this.readyState===4 && this.responseText.length>0) ? true : false; 
    }); 
} 
export default {isValid} 

Сейчас console.log(isValid(this.props.params.id) в componentWillMount() всегда печатает undefined, независимо от того, id действителен или нет. Кажется, могут быть две проблемы: либо я неправильно возвращаю логический ответ isValid(), либо ошибочно использую componentWillMount(). Я тоже подумал о docs и узнал, что componentWillMount() фактически запускается до render().

Может ли кто-нибудь указать на реальную проблему и исправить меня, где я делаю неправильно?

+1

Что вызывает Foo? это параметры, исходящие от реагирующего маршрутизатора? если да, то можете ли вы показать нам, как ваши маршруты настроены? –

+0

@JoPeyper Я обновил вопрос, указав соответствующие строки 'routes.js'. Пожалуйста, не стесняйтесь спрашивать, нет ли чего-то еще. – adi

ответ

-1

Непонятно, что называется компонентом Foo. Но похоже, что у вас отсутствует конструктор в классе Foo.

class Foo extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { check : true }; 
    } 
    componentWillMount() { 
    console.log(this.props.params.id); 
    } 
    render() { 
     //... 
    } 
} 

См. React State Docs для получения дополнительной информации.

+0

не представляется полезным. Также было бы 'this.state' в конструкторе, поскольку только состояние будет генерировать ошибку' undefined' – adi

+1

Спасибо, что я исправил, чтобы сказать 'this.state' – styfle

0

Похоже, вы пытаетесь выполнить условный рендеринг. Я столкнулся с этой проблемой, когда обучение реагирует самостоятельно (предположим, что это то, что вы ищете). Если это так, то это, как вы бы это сделать:



Так, в приведенном выше блоке кода, вы могли бы сделать какие-то проверки состояния, чтобы увидеть, если this.props.params .id === «некоторая строка», а затем, когда это правда, она отобразит первый набор div.

Сообщите мне, если это не работает или вы ищете другое решение!

+0

Кроме того, какие идентификаторы вы ищете на своем маршруте? Вы пытаетесь выполнить проверку по электронной почте? – Mason0958

+0

Я обновил часть рендеринга для вас. Пожалуйста, дайте ему взглянуть снова, вот как я применяю кондиционер, но я не думаю, что это проблема кондиционирования здесь. Проблема в том, что 'console.log' в' componentWillMount() 'всегда печатает' undefined', тогда как это должно быть либо 'true', либо' false'. Что касается валидации, то его просто случайный (вид продукта) идентификатор ошибки – adi

+0

также упомянутое трехмерное решение для кондиционирования только для одной строки для возврата/рендеринга. Есть много других потоков для [условного рендеринга в реакции] (http://stackoverflow.com/questions/22538638/how-to-have-conditional-elements-and-keep-dry-with-facebook-reacts-jsx) – adi

1

Примечание: Я не уверен, что остальная часть вашего XMLHttpRequest работает, поскольку я никогда не работал с ней напрямую, используя библиотеки, чтобы управлять им для меня, как выборка или аксиомы.

Вопрос в вашем действительном методе.

function isValid(id){ 
    let url = 'https://some/api/url/'; 
    return fetchId('POST', url, id, function(){ 
    return (this.readyState===4 && this.responseText.length>0) ? true : false; 
    }); 
} 

вопрос является возвращение логического значения внутри функции, а функция isValid фактически возвращает результат функции fetchId (который не возвращает ничего, поэтому вы регистрируете undefined).

Почему это происходит?

Ну, ваш запрос выполнен в фоновом режиме и не блокирует выполнение. Поэтому в конце вашей функции isValid у нее нет возвращаемого логического значения.

Что вы можете сделать?

Функция isValid должна принимать обратный вызов для задержки его установки состояния до завершения запроса, аналогично функции fetchId.

function isValid(id, callback){ 
    let url = 'https://some/api/url/'; 
    fetchId('POST', url, id, function(){ 
    callback(this.readyState===4 && this.responseText.length>0) 
    }); 
} 

и вы называете это как так

componentWillMount(){ 
    isValid(this.props.params.id, valid => { 
    if (!valid) { 
     console.log(isValid(this.props.params.id)); 
     this.setState({ 
     check : false 
     }); 
    } 
    }); 
} 

Но у меня есть обратные вызовы внутри обратных вызовов и его все становится слишком трудно следовать!

Вы не ошибаетесь. Эти виды взаимодействий становятся очень грязными, если вы пытаетесь полностью их выполнять внутри своего реагирующего компонента. Вы можете легко отделить свои заботы от государственного управления, действий и взглядов, используя redux и react-redux.

+0

наконец-то правильный ответ, хотя эти обратные вызовы не кажутся идеальными. Я применил ваши изменения с действительным идентификатором и в ответ, он отображает правую часть, но в течение секунды, он снова печатает 'undefined' и повторно отображает другую часть – adi

+0

Перед условием' if (! Valid) ... ', я добавил 'console.log (valid)' и он печатает 'false' дважды и' true' один раз. Это означает, что функция работает трижды, любая идея, почему это происходит? – adi

+1

Возможно, что-то другое заставляет компонент монтировать несколько раз. Трудно сказать, не запуская и не отлаживая его. Чтобы все было правильно, вы действительно захотите посмотреть на redux. Redux изменит то, как вы думаете о состоянии в своем компоненте, и упростите сложные состояния загрузки. –